[U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM

# bootefi doesn't work with this patch set yet
This patch set came from the past discussion[1] on my "removable device support" patch and is intended to be an attempt to integrate efi objects into u-boot's Driver Model as much seamlessly as possible.
[1] https://lists.denx.de/pipermail/u-boot/2019-January/354010.html
Since this patch is a prototype (or POC, Proof-Of-Concept), the aim here is to discuss further about how in a better shape we will be able to merge the two worlds.
After RFC, Simon suggested that efi protocols could be also presented as DM devices. This is a major change in RFC v2.
Basic idea is * efi_root is a DM device * Any efi object, refered to by efi_handle_t in UEFI world, has a corresponding DM device. - define efi_handle_t as "struct udevice *" - for efi_disk, * add "struct efi_disk_obj" to blk_desc - for the objects below, there is only one instance for each and so they are currently global data: efi_gop_obj, efi_net_obj, simple_text_output_mode - for loaded_image, * link efi_loaded_image_obj to device's platdata
* Any efi protocol has a corresponding DM device. - link "struct efi_handler" to device's uclass_platdata - be a child of a efi object (hence DM device) in DM device hierarchy so that enumerating protocols belonging to efi object is done by traversing the tree.
* Any efi object which has a backing DM device should be created when that DM device is detected (and probed). * For efi_disk (or any object with EFI_BLOCK_IO_PROTOCOL), - add UCLASS_PARTITION - put partitions under a raw block device - partitions as well as raw devices can be efi_disk
With those extensive changes, there still exists plenty of "wrapper" code. Do you have any idea to reduce it?
***** Example operation ****** (Two scsi disks, one with no partition, one with two partitions)
=> efi dev EFI: Initializing UCLASS_EFI_DRIVER Device Device Path ================ ==================== 000000007eef9470 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b) => scsi rescan
Reset SCSI scanning bus for devices... Target spinup took 0 ms. Target spinup took 0 ms. SATA link 2 timeout. SATA link 3 timeout. SATA link 4 timeout. SATA link 5 timeout. AHCI 0001.0000 32 slots 6 ports 1.5 Gbps 0x3f impl SATA mode flags: 64bit ncq only Device 0: (0:0) Vendor: ATA Prod.: QEMU HARDDISK Rev: 2.5+ Type: Hard Disk Capacity: 16.0 MB = 0.0 GB (32768 x 512) Device 0: (1:0) Vendor: ATA Prod.: QEMU HARDDISK Rev: 2.5+ Type: Hard Disk Capacity: 256.0 MB = 0.2 GB (524288 x 512) => efi dev Device Device Path ================ ==================== 000000007eef9470 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b) 000000007ef01c90 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(0,0) 000000007ef04910 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(1,0) 000000007ef04ee0 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(1,0)/HD(335544330,MBR,0x086246ba,0x17ff4f1a0,0x7eee3770) 000000007ef055a0 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(1,0)/HD(335544330,MBR,0x086246ba,0x17ff4f1a0,0x7eee3770) => dm tree Class index Probed Driver Name ----------------------------------------------------------- root 0 [ + ] root_driver root_driver simple_bus 0 [ ] generic_simple_bus |-- platform@c000000 virtio 0 [ + ] virtio-mmio |-- virtio_mmio@a000000
[snip]
pci 0 [ + ] pci_generic_ecam |-- pcie@10000000 pci_generi 0 [ ] pci_generic_drv | |-- pci_0:0.0 virtio 32 [ ] virtio-pci.l | |-- virtio-pci.l#0 ahci 0 [ + ] ahci_pci | `-- ahci_pci scsi 0 [ + ] ahci_scsi | `-- ahci_scsi blk 0 [ + ] scsi_blk | |-- ahci_scsi.id0lun0 efi_protoc 8 [ + ] efi_disk | | |-- BLOCK_IO efi_protoc 9 [ + ] efi_device_path | | `-- Scsi(0,0) blk 1 [ + ] scsi_blk | `-- ahci_scsi.id1lun0 efi_protoc 10 [ + ] efi_disk | |-- BLOCK_IO efi_protoc 11 [ + ] efi_device_path | |-- Scsi(1,0) partition 0 [ + ] blk_partition | |-- ahci_scsi.id1lun0:1 efi_protoc 12 [ + ] efi_disk | | |-- BLOCK_IO efi_protoc 13 [ + ] efi_device_path | | |-- HD(335544330,MBR,0x086246ba,0x17ff4f1a0,0x7eee3770) efi_protoc 14 [ + ] efi_simple_file_syst | | `-- SIMPLE_FILE_SYSTEM partition 1 [ + ] blk_partition | `-- ahci_scsi.id1lun0:2 efi_protoc 15 [ + ] efi_disk | |-- BLOCK_IO efi_protoc 16 [ + ] efi_device_path | |-- HD(335544330,MBR,0x086246ba,0x17ff4f1a0,0x7eee3770) efi_protoc 17 [ + ] efi_simple_file_syst | `-- SIMPLE_FILE_SYSTEM rtc 0 [ ] rtc-pl031 |-- pl031@9010000 serial 0 [ ] serial_pl01x |-- pl011@9050000 serial 1 [ + ] serial_pl01x |-- pl011@9000000 efi_protoc 0 [ + ] efi_simple_text_outp | |-- SIMPLE_TEXT_OUTPUT efi_protoc 1 [ + ] efi_simple_text_inpu | |-- SIMPLE_TEXT_INPUT efi_protoc 2 [ + ] efi_simple_text_inpu | `-- SIMPLE_TEXT_INPUT_EX mtd 0 [ + ] cfi_flash |-- flash@0 firmware 0 [ + ] psci |-- psci sysreset 0 [ ] psci-sysreset | `-- psci-sysreset efi 0 [ + ] efi_root `-- UEFI sub system efi_protoc 3 [ + ] efi_device_path |-- VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b) efi_protoc 4 [ + ] efi_device_path_to_t |-- DEVICE_PATH_TO_TEXT efi_protoc 5 [ + ] efi_device_path_util |-- DEVICE_PATH_UTILITIES efi_protoc 6 [ + ] efi_unicode_collatio |-- en efi_driver 0 [ + ] EFI block driver `-- EFI block driver efi_protoc 7 [ + ] efi_driver_binding `-- DRIVER_BINDING
Thanks, -Takahiro Akashi
AKASHI Takahiro (15): efi_loader: efi objects and protocols as DM devices efi_loader: boottime: convert efi_loaded_image_obj to DM efi_loader: image_loader: aligned with DM efi_driver: rename UCLASS_EFI to UCLASS_EFI_DRIVER efi_loader: convert efi_root_node to DM efi_loader: device path: convert efi_device_path to DM efi_loader: unicode_collation: converted to DM efi_loader: console: convert efi console input/output to DM efi_loader: net: convert efi_net_obj to DM efi_loader: gop: convert efi_gop_obj to DM dm: blk: add UCLASS_PARTITION efi_loader: disk: convert efi_disk_obj to DM drivers: align block device drivers with DM-efi integration efi_driver: converted to DM cmd: efidebug: aligned with DM-efi integration
cmd/bootefi.c | 61 +-- cmd/efidebug.c | 5 +- common/usb_storage.c | 27 +- drivers/block/blk-uclass.c | 61 +++ drivers/scsi/scsi.c | 22 + drivers/serial/serial-uclass.c | 6 + drivers/video/video-uclass.c | 9 + include/blk.h | 24 + include/dm/device.h | 3 + include/dm/uclass-id.h | 6 +- include/efi.h | 4 +- include/efi_loader.h | 50 +- lib/efi_driver/efi_block_device.c | 36 +- lib/efi_driver/efi_uclass.c | 37 +- lib/efi_loader/efi_boottime.c | 605 ++++++++++++++------- lib/efi_loader/efi_console.c | 64 ++- lib/efi_loader/efi_device_path.c | 136 +++-- lib/efi_loader/efi_device_path_to_text.c | 55 ++ lib/efi_loader/efi_device_path_utilities.c | 14 + lib/efi_loader/efi_disk.c | 216 +++++--- lib/efi_loader/efi_file.c | 14 + lib/efi_loader/efi_gop.c | 28 +- lib/efi_loader/efi_image_loader.c | 61 ++- lib/efi_loader/efi_net.c | 50 +- lib/efi_loader/efi_root_node.c | 14 +- lib/efi_loader/efi_setup.c | 60 +- lib/efi_loader/efi_unicode_collation.c | 19 + net/eth-uclass.c | 5 + 28 files changed, 1226 insertions(+), 466 deletions(-)

All efi objects are presented as DM devices, either existing device types or efi-specific, and efi_handle_t is an opaque pointer to "struct udevice."
We still maintain efi_obj_list as it is quite inefficient to traverse the DM hierarchy to find any efi objects, which are just part of it.
All efi protocols are also presented as DM devices, replacing "struct efi_handler" with "struct udevice." So searching for an efi protocol is nothing but traversing child nodes under a device.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- include/dm/device.h | 3 + include/dm/uclass-id.h | 2 + include/efi.h | 4 +- include/efi_loader.h | 37 +-- lib/efi_loader/efi_boottime.c | 544 ++++++++++++++++++++++++---------- 5 files changed, 400 insertions(+), 190 deletions(-)
diff --git a/include/dm/device.h b/include/dm/device.h index 27a6d7b9fdb0..0d82402c8e70 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -146,6 +146,9 @@ struct udevice { #ifdef CONFIG_DEVRES struct list_head devres_head; #endif +#ifdef CONFIG_EFI_LOADER + void *efi_obj; +#endif };
/* Maximum sequence number supported */ diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index f3bafb3c6353..fb0ab40891c8 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -40,6 +40,8 @@ enum uclass_id { UCLASS_DISPLAY, /* Display (e.g. DisplayPort, HDMI) */ UCLASS_DMA, /* Direct Memory Access */ UCLASS_EFI, /* EFI managed devices */ + UCLASS_EFI_OBJECT, /* EFI managed objects */ + UCLASS_EFI_PROTOCOL, /* EFI managed protocols */ UCLASS_ETH, /* Ethernet device */ UCLASS_FIRMWARE, /* Firmware */ UCLASS_FS_FIRMWARE_LOADER, /* Generic loader */ diff --git a/include/efi.h b/include/efi.h index b5e2c64f38b5..58902299a9a0 100644 --- a/include/efi.h +++ b/include/efi.h @@ -96,7 +96,9 @@ typedef struct { typedef unsigned long efi_status_t; typedef u64 efi_physical_addr_t; typedef u64 efi_virtual_addr_t; -typedef struct efi_object *efi_handle_t; +/* Eventually this should be 'void *' */ +struct udevice; +typedef struct udevice *efi_handle_t;
#define EFI_GUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \ {{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, \ diff --git a/include/efi_loader.h b/include/efi_loader.h index 3077a1e9d58b..4d5e22564a72 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -167,38 +167,12 @@ struct efi_open_protocol_info_item { * protocol GUID to the respective protocol interface */ struct efi_handler { - /* Link to the list of protocols of a handle */ - struct list_head link; const efi_guid_t *guid; void *protocol_interface; /* Link to the list of open protocol info items */ struct list_head open_infos; };
-/** - * struct efi_object - dereferenced EFI handle - * - * @link: pointers to put the handle into a linked list - * @protocols: linked list with the protocol interfaces installed on this - * handle - * - * UEFI offers a flexible and expandable object model. The objects in the UEFI - * API are devices, drivers, and loaded images. struct efi_object is our storage - * structure for these objects. - * - * When including this structure into a larger structure always put it first so - * that when deleting a handle the whole encompassing structure can be freed. - * - * A pointer to this structure is referred to as a handle. Typedef efi_handle_t - * has been created for such pointers. - */ -struct efi_object { - /* Every UEFI object is part of a global object list */ - struct list_head link; - /* The list of protocols */ - struct list_head protocols; -}; - /** * struct efi_loaded_image_obj - handle of a loaded image * @@ -209,7 +183,6 @@ struct efi_object { * @entry: entry address of the relocated image */ struct efi_loaded_image_obj { - struct efi_object header; void *reloc_base; aligned_u64 reloc_size; efi_status_t exit_status; @@ -312,18 +285,18 @@ void efi_restore_gd(void); void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map); /* Call this to set the current device name */ void efi_set_bootdev(const char *dev, const char *devnr, const char *path); +/* Go through all the efi objects and call func() for each */ +efi_status_t efi_foreach_dev(int (*func)(struct udevice *, void *), void *arg); /* Add a new object to the object list. */ -void efi_add_handle(efi_handle_t obj); +efi_status_t efi_add_handle(struct udevice *dev); /* Create handle */ -efi_status_t efi_create_handle(efi_handle_t *handle); +efi_status_t efi_create_handle(efi_handle_t *handle, char *name); /* Delete handle */ void efi_delete_handle(efi_handle_t obj); -/* Call this to validate a handle and find the EFI object for it */ -struct efi_object *efi_search_obj(const efi_handle_t handle); /* Find a protocol on a handle */ efi_status_t efi_search_protocol(const efi_handle_t handle, const efi_guid_t *protocol_guid, - struct efi_handler **handler); + struct udevice **protocol); /* Install new protocol on a handle */ efi_status_t efi_add_protocol(const efi_handle_t handle, const efi_guid_t *protocol, diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 291bc1bd35f9..d23e4fbbdf23 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -7,6 +7,10 @@
#include <common.h> #include <div64.h> +#include <dm.h> +#include <dm/device-internal.h> +#include <dm/lists.h> +#include <dm/root.h> #include <efi_loader.h> #include <environment.h> #include <malloc.h> @@ -17,6 +21,13 @@
DECLARE_GLOBAL_DATA_PTR;
+struct efi_object { + /* Every UEFI object is part of a global object list */ + struct list_head link; + /* The backing uclass device */ + struct udevice *dev; +}; + /* Task priority level */ static efi_uintn_t efi_tpl = TPL_APPLICATION;
@@ -418,70 +429,125 @@ static efi_status_t EFIAPI efi_free_pool_ext(void *buffer) return EFI_EXIT(r); }
+static bool efi_is_valid(efi_handle_t handle) +{ + struct efi_object *efiobj; + + list_for_each_entry(efiobj, &efi_obj_list, link) { + if (efiobj->dev == handle) + return true; + } + + return false; +} + +/** + * efi_foreach_dev() + */ +efi_status_t efi_foreach_dev(int (*func)(struct udevice *, void *), void *arg) +{ + int ret; + struct efi_object *efiobj; + + list_for_each_entry(efiobj, &efi_obj_list, link) { + ret = (*func)(efiobj->dev, arg); + if (ret == 1) + return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; +} + /** * efi_add_handle() - add a new object to the object list - * @obj: object to be added + * @handle: udevice to be added as object * * The protocols list is initialized. The object handle is set. */ -void efi_add_handle(efi_handle_t handle) +efi_status_t efi_add_handle(struct udevice *dev) { - if (!handle) - return; - INIT_LIST_HEAD(&handle->protocols); - list_add_tail(&handle->link, &efi_obj_list); + struct efi_object *efi_obj; + + if (!dev) + return EFI_INVALID_PARAMETER; + + efi_obj = calloc(1, sizeof(struct efi_object)); + if (!efi_obj) + return EFI_OUT_OF_RESOURCES; + + efi_obj->dev = dev; + dev->efi_obj = efi_obj; + list_add_tail(&efi_obj->link, &efi_obj_list); + + return EFI_SUCCESS; }
/** * efi_create_handle() - create handle * @handle: new handle + * @name: name * * Return: status code */ -efi_status_t efi_create_handle(efi_handle_t *handle) +efi_status_t efi_create_handle(efi_handle_t *handle, char *name) { - struct efi_object *obj; + struct udevice *dev; + efi_status_t ret; + + if (!handle) + return EFI_INVALID_PARAMETER;
- obj = calloc(1, sizeof(struct efi_object)); - if (!obj) + ret = device_bind_driver(dm_root(), "efi_dumb_object", name, &dev); + if (ret) return EFI_OUT_OF_RESOURCES;
- efi_add_handle(obj); - *handle = obj; + ret = efi_add_handle(dev); + if (ret) +#ifdef CONFIG_DM_DEVICE_REMOVE + device_unbind(dev); +#else + 0; +#endif + else + *handle = dev;
- return EFI_SUCCESS; + return ret; }
/** * efi_search_protocol() - find a protocol on a handle. * @handle: handle * @protocol_guid: GUID of the protocol - * @handler: reference to the protocol + * @protocol: reference to the protocol * * Return: status code */ efi_status_t efi_search_protocol(const efi_handle_t handle, const efi_guid_t *protocol_guid, - struct efi_handler **handler) + struct udevice **protocol) { - struct efi_object *efiobj; - struct list_head *lhandle; + struct udevice *dev, *child; + struct efi_handler *handler;
if (!handle || !protocol_guid) return EFI_INVALID_PARAMETER; - efiobj = efi_search_obj(handle); - if (!efiobj) + + if (!efi_is_valid(handle)) return EFI_INVALID_PARAMETER; - list_for_each(lhandle, &efiobj->protocols) { - struct efi_handler *protocol; + dev = handle; + + list_for_each_entry(child, &dev->child_head, sibling_node) { + if (child->driver->id != UCLASS_EFI_PROTOCOL) + continue;
- protocol = list_entry(lhandle, struct efi_handler, link); - if (!guidcmp(protocol->guid, protocol_guid)) { - if (handler) - *handler = protocol; + handler = child->uclass_platdata; + if (!guidcmp(handler->guid, protocol_guid)) { + if (protocol) + *protocol = child; return EFI_SUCCESS; } } + return EFI_NOT_FOUND; }
@@ -494,21 +560,33 @@ efi_status_t efi_search_protocol(const efi_handle_t handle, * Return: status code */ efi_status_t efi_remove_protocol(const efi_handle_t handle, - const efi_guid_t *protocol, + const efi_guid_t *protocol_guid, void *protocol_interface) { + struct udevice *protocol; struct efi_handler *handler; efi_status_t ret;
- ret = efi_search_protocol(handle, protocol, &handler); + ret = efi_search_protocol(handle, protocol_guid, &protocol); if (ret != EFI_SUCCESS) return ret; - if (guidcmp(handler->guid, protocol)) + + handler = protocol->uclass_platdata; + if (guidcmp(handler->guid, protocol_guid)) return EFI_INVALID_PARAMETER; + if (handler->protocol_interface != protocol_interface) return EFI_INVALID_PARAMETER; + +#if 1 /* FIXME */ + device_free(protocol); +#ifdef CONFIG_DM_DEVICE_REMOVE + device_unbind(protocol); +#endif +#else list_del(&handler->link); free(handler); +#endif return EFI_SUCCESS; }
@@ -520,24 +598,46 @@ efi_status_t efi_remove_protocol(const efi_handle_t handle, */ efi_status_t efi_remove_all_protocols(const efi_handle_t handle) { - struct efi_object *efiobj; - struct efi_handler *protocol; - struct efi_handler *pos; + struct udevice *dev, *child, *pos; + struct efi_handler *handler;
- efiobj = efi_search_obj(handle); - if (!efiobj) + if (!efi_is_valid(handle)) return EFI_INVALID_PARAMETER; - list_for_each_entry_safe(protocol, pos, &efiobj->protocols, link) { + dev = handle; + + list_for_each_entry_safe(child, pos, &dev->child_head, sibling_node) { efi_status_t ret;
- ret = efi_remove_protocol(handle, protocol->guid, - protocol->protocol_interface); + if (child->driver->id != UCLASS_EFI_PROTOCOL) + continue; + + handler = child->uclass_platdata; + ret = efi_remove_protocol(handle, handler->guid, + handler->protocol_interface); if (ret != EFI_SUCCESS) return ret; } return EFI_SUCCESS; }
+static void efi_remove_handle(efi_handle_t handle) +{ + struct udevice *dev = handle; + struct efi_object *efi_obj = dev->efi_obj; + + list_del(&efi_obj->link); + free(efi_obj); + + /* free only if internal object */ + if (dev->driver->id == UCLASS_EFI_OBJECT) { +#ifdef CONFIG_DM_DEVICE_REMOVE + device_unbind(dev); +#endif + } + + /* native device handle should be taken care of by caller */ +} + /** * efi_delete_handle() - delete handle * @@ -547,9 +647,9 @@ void efi_delete_handle(efi_handle_t handle) { if (!handle) return; + efi_remove_all_protocols(handle); - list_del(&handle->link); - free(handle); + efi_remove_handle(handle); }
/** @@ -923,24 +1023,6 @@ static efi_status_t EFIAPI efi_check_event(struct efi_event *event) return EFI_EXIT(EFI_NOT_READY); }
-/** - * efi_search_obj() - find the internal EFI object for a handle - * @handle: handle to find - * - * Return: EFI object - */ -struct efi_object *efi_search_obj(const efi_handle_t handle) -{ - struct efi_object *efiobj; - - list_for_each_entry(efiobj, &efi_obj_list, link) { - if (efiobj == handle) - return efiobj; - } - - return NULL; -} - /** * efi_open_protocol_info_entry() - create open protocol info entry and add it * to a protocol @@ -976,6 +1058,88 @@ static efi_status_t efi_delete_open_info( return EFI_SUCCESS; }
+/* FIXME */ +extern const efi_guid_t efi_guid_text_input_ex_protocol; +extern const efi_guid_t efi_guid_text_input_protocol; +extern const efi_guid_t efi_guid_text_output_protocol; +extern const efi_guid_t efi_gop_guid; +extern const efi_guid_t efi_net_guid; +extern const efi_guid_t efi_pxe_guid; + +/* TODO: add entries one by one */ +static struct { + const efi_guid_t *guid; + const char *drv_name; +} protocol_list[] = { + { + .guid = &efi_guid_text_input_ex_protocol, + .drv_name = "efi_simple_text_input_ex", + }, + { + .guid = &efi_guid_text_input_protocol, + .drv_name = "efi_simple_text_input", + }, + { + .guid = &efi_guid_text_output_protocol, + .drv_name = "efi_simple_text_output", + }, + { + .guid = &efi_guid_device_path, + .drv_name = "efi_device_path", + }, + { + .guid = &efi_guid_device_path_to_text_protocol, + .drv_name = "efi_device_path_to_text", + }, + { + .guid = &efi_guid_device_path_utilities_protocol, + .drv_name = "efi_device_path_utils", + }, +#if defined(CONFIG_LCD) || defined(CONFIG_DM_VIDEO) + { + .guid = &efi_gop_guid, + .drv_name = "efi_gop", + }, +#endif +#if defined(CONFIG_NET) + { + .guid = &efi_net_guid, + .drv_name = "efi_net", + }, + { + .guid = &efi_net_guid, + .drv_name = "efi_pxe", + }, +#endif + { + .guid = &efi_guid_unicode_collation_protocol, + .drv_name = "efi_unicode_collation", + }, + { + .guid = &efi_block_io_guid, + .drv_name = "efi_disk", + }, + { + .guid = &efi_simple_file_system_protocol_guid, + .drv_name = "efi_simple_file_system", + }, + { + .guid = &efi_guid_driver_binding_protocol, + .drv_name = "efi_driver_binding", + }, +}; + +static const char *get_protocol_drv_name(const efi_guid_t *guid) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(protocol_list); i++) + if (!guidcmp(protocol_list[i].guid, guid)) + return protocol_list[i].drv_name; + + return "efi_protocol"; +} + /** * efi_add_protocol() - install new protocol on a handle * @handle: handle on which the protocol shall be installed @@ -985,28 +1149,36 @@ static efi_status_t efi_delete_open_info( * Return: status code */ efi_status_t efi_add_protocol(const efi_handle_t handle, - const efi_guid_t *protocol, + const efi_guid_t *protocol_guid, void *protocol_interface) { - struct efi_object *efiobj; + struct udevice *dev, *protocol; struct efi_handler *handler; efi_status_t ret;
- efiobj = efi_search_obj(handle); - if (!efiobj) + if (!efi_is_valid(handle)) return EFI_INVALID_PARAMETER; - ret = efi_search_protocol(handle, protocol, NULL); + dev = handle; + + ret = efi_search_protocol(handle, protocol_guid, NULL); if (ret != EFI_NOT_FOUND) return EFI_INVALID_PARAMETER; - handler = calloc(1, sizeof(struct efi_handler)); - if (!handler) + + ret = device_bind_driver(dev, get_protocol_drv_name(protocol_guid), + "(PROTO)", &protocol); + if (ret) return EFI_OUT_OF_RESOURCES; - handler->guid = protocol; + + handler = protocol->uclass_platdata; + handler->guid = protocol_guid; handler->protocol_interface = protocol_interface; INIT_LIST_HEAD(&handler->open_infos); - list_add_tail(&handler->link, &efiobj->protocols); - if (!guidcmp(&efi_guid_device_path, protocol)) + + device_probe(protocol); + + if (!guidcmp(&efi_guid_device_path, protocol_guid)) EFI_PRINT("installed device path '%pD'\n", protocol_interface); + return EFI_SUCCESS; }
@@ -1042,7 +1214,7 @@ static efi_status_t EFIAPI efi_install_protocol_interface(
/* Create new handle if requested. */ if (!*handle) { - r = efi_create_handle(handle); + r = efi_create_handle(handle, "(NO NAME)"); if (r != EFI_SUCCESS) goto out; debug("%sEFI: new handle %p\n", indent_string(nesting_level), @@ -1073,13 +1245,20 @@ static efi_status_t efi_get_drivers(efi_handle_t handle, efi_uintn_t *number_of_drivers, efi_handle_t **driver_handle_buffer) { + struct udevice *dev, *child; struct efi_handler *handler; struct efi_open_protocol_info_item *item; efi_uintn_t count = 0, i; bool duplicate;
+ dev = handle; + /* Count all driver associations */ - list_for_each_entry(handler, &handle->protocols, link) { + list_for_each_entry(child, &dev->child_head, sibling_node) { + if (child->driver->id != UCLASS_EFI_PROTOCOL) + continue; + + handler = child->uclass_platdata; if (protocol && guidcmp(handler->guid, protocol)) continue; list_for_each_entry(item, &handler->open_infos, link) { @@ -1097,7 +1276,11 @@ static efi_status_t efi_get_drivers(efi_handle_t handle, if (!*driver_handle_buffer) return EFI_OUT_OF_RESOURCES; /* Collect unique driver handles */ - list_for_each_entry(handler, &handle->protocols, link) { + list_for_each_entry(child, &dev->child_head, sibling_node) { + if (child->driver->id != UCLASS_EFI_PROTOCOL) + continue; + + handler = child->uclass_platdata; if (protocol && guidcmp(handler->guid, protocol)) continue; list_for_each_entry(item, &handler->open_infos, link) { @@ -1173,28 +1356,27 @@ static efi_status_t efi_disconnect_all_drivers * * Return: status code */ -static efi_status_t efi_uninstall_protocol - (efi_handle_t handle, const efi_guid_t *protocol, - void *protocol_interface) +static efi_status_t efi_uninstall_protocol(efi_handle_t handle, + const efi_guid_t *protocol_guid, + void *protocol_interface) { - struct efi_object *efiobj; + struct udevice *protocol; struct efi_handler *handler; struct efi_open_protocol_info_item *item; struct efi_open_protocol_info_item *pos; efi_status_t r;
- /* Check handle */ - efiobj = efi_search_obj(handle); - if (!efiobj) { - r = EFI_INVALID_PARAMETER; - goto out; - } + if (!efi_is_valid(handle)) + return EFI_INVALID_PARAMETER; + /* Find the protocol on the handle */ - r = efi_search_protocol(handle, protocol, &handler); + r = efi_search_protocol(handle, protocol_guid, &protocol); if (r != EFI_SUCCESS) goto out; + handler = protocol->uclass_platdata; + /* Disconnect controllers */ - efi_disconnect_all_drivers(efiobj, protocol, NULL); + efi_disconnect_all_drivers(handle, protocol_guid, NULL); if (!list_empty(&handler->open_infos)) { r = EFI_ACCESS_DENIED; goto out; @@ -1211,7 +1393,7 @@ static efi_status_t efi_uninstall_protocol r = EFI_ACCESS_DENIED; goto out; } - r = efi_remove_protocol(handle, protocol, protocol_interface); + r = efi_remove_protocol(handle, protocol_guid, protocol_interface); out: return r; } @@ -1242,10 +1424,9 @@ static efi_status_t EFIAPI efi_uninstall_protocol_interface goto out;
/* If the last protocol has been removed, delete the handle. */ - if (list_empty(&handle->protocols)) { - list_del(&handle->link); - free(handle); - } + if (device_find_first_child_by_uclass(handle, UCLASS_EFI_PROTOCOL, + NULL)) + efi_remove_handle(handle); out: return EFI_EXIT(ret); } @@ -1352,7 +1533,7 @@ static efi_status_t efi_locate_handle(
/* Count how much space we need */ list_for_each_entry(efiobj, &efi_obj_list, link) { - if (!efi_search(search_type, protocol, search_key, efiobj)) + if (!efi_search(search_type, protocol, search_key, efiobj->dev)) size += sizeof(void *); }
@@ -1367,8 +1548,8 @@ static efi_status_t efi_locate_handle(
/* Then fill the array */ list_for_each_entry(efiobj, &efi_obj_list, link) { - if (!efi_search(search_type, protocol, search_key, efiobj)) - *buffer++ = efiobj; + if (!efi_search(search_type, protocol, search_key, efiobj->dev)) + *buffer++ = efiobj->dev; }
return EFI_SUCCESS; @@ -2012,25 +2193,27 @@ static efi_status_t EFIAPI efi_set_watchdog_timer(unsigned long timeout, * Return: status code */ static efi_status_t EFIAPI efi_close_protocol(efi_handle_t handle, - const efi_guid_t *protocol, + const efi_guid_t *protocol_guid, efi_handle_t agent_handle, efi_handle_t controller_handle) { + struct udevice *protocol; struct efi_handler *handler; struct efi_open_protocol_info_item *item; struct efi_open_protocol_info_item *pos; efi_status_t r;
- EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, agent_handle, + EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol_guid, agent_handle, controller_handle);
if (!agent_handle) { r = EFI_INVALID_PARAMETER; goto out; } - r = efi_search_protocol(handle, protocol, &handler); + r = efi_search_protocol(handle, protocol_guid, &protocol); if (r != EFI_SUCCESS) goto out; + handler = protocol->uclass_platdata;
r = EFI_NOT_FOUND; list_for_each_entry_safe(item, pos, &handler->open_infos, link) { @@ -2061,17 +2244,18 @@ out: * Return: status code */ static efi_status_t EFIAPI efi_open_protocol_information( - efi_handle_t handle, const efi_guid_t *protocol, + efi_handle_t handle, const efi_guid_t *protocol_guid, struct efi_open_protocol_info_entry **entry_buffer, efi_uintn_t *entry_count) { unsigned long buffer_size; unsigned long count; + struct udevice *protocol; struct efi_handler *handler; struct efi_open_protocol_info_item *item; efi_status_t r;
- EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, entry_buffer, + EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol_guid, entry_buffer, entry_count);
/* Check parameters */ @@ -2079,9 +2263,10 @@ static efi_status_t EFIAPI efi_open_protocol_information( r = EFI_INVALID_PARAMETER; goto out; } - r = efi_search_protocol(handle, protocol, &handler); + r = efi_search_protocol(handle, protocol_guid, &protocol); if (r != EFI_SUCCESS) goto out; + handler = protocol->uclass_platdata;
/* Count entries */ count = 0; @@ -2127,9 +2312,8 @@ static efi_status_t EFIAPI efi_protocols_per_handle( efi_handle_t handle, efi_guid_t ***protocol_buffer, efi_uintn_t *protocol_buffer_count) { + struct udevice *dev, *child; unsigned long buffer_size; - struct efi_object *efiobj; - struct list_head *protocol_handle; efi_status_t r;
EFI_ENTRY("%p, %p, %p", handle, protocol_buffer, @@ -2141,12 +2325,15 @@ static efi_status_t EFIAPI efi_protocols_per_handle( *protocol_buffer = NULL; *protocol_buffer_count = 0;
- efiobj = efi_search_obj(handle); - if (!efiobj) - return EFI_EXIT(EFI_INVALID_PARAMETER); + if (!efi_is_valid(handle)) + return EFI_INVALID_PARAMETER; + dev = handle;
/* Count protocols */ - list_for_each(protocol_handle, &efiobj->protocols) { + list_for_each_entry(child, &dev->child_head, sibling_node) { + if (child->driver->id != UCLASS_EFI_PROTOCOL) + continue; + ++*protocol_buffer_count; }
@@ -2159,12 +2346,15 @@ static efi_status_t EFIAPI efi_protocols_per_handle( (void **)protocol_buffer); if (r != EFI_SUCCESS) return EFI_EXIT(r); - list_for_each(protocol_handle, &efiobj->protocols) { - struct efi_handler *protocol;
- protocol = list_entry(protocol_handle, - struct efi_handler, link); - (*protocol_buffer)[j] = (void *)protocol->guid; + list_for_each_entry(child, &dev->child_head, sibling_node) { + struct efi_handler *handler; + + if (child->driver->id != UCLASS_EFI_PROTOCOL) + continue; + + handler = child->uclass_platdata; + (*protocol_buffer)[j] = (void *)handler->guid; ++j; } } @@ -2233,26 +2423,27 @@ out: * * Return: status code */ -static efi_status_t EFIAPI efi_locate_protocol(const efi_guid_t *protocol, +static efi_status_t EFIAPI efi_locate_protocol(const efi_guid_t *protocol_guid, void *registration, void **protocol_interface) { - struct list_head *lhandle; + struct efi_object *efiobj; efi_status_t ret;
- EFI_ENTRY("%pUl, %p, %p", protocol, registration, protocol_interface); + EFI_ENTRY("%pUl, %p, %p", protocol_guid, registration, + protocol_interface);
- if (!protocol || !protocol_interface) + if (!protocol_guid || !protocol_interface) return EFI_EXIT(EFI_INVALID_PARAMETER);
- list_for_each(lhandle, &efi_obj_list) { - struct efi_object *efiobj; + list_for_each_entry(efiobj, &efi_obj_list, link) { struct efi_handler *handler; + struct udevice *protocol;
- efiobj = list_entry(lhandle, struct efi_object, link); - - ret = efi_search_protocol(efiobj, protocol, &handler); + ret = efi_search_protocol(efiobj->dev, protocol_guid, + &protocol); if (ret == EFI_SUCCESS) { + handler = protocol->uclass_platdata; *protocol_interface = handler->protocol_interface; return EFI_EXIT(EFI_SUCCESS); } @@ -2277,12 +2468,13 @@ static efi_status_t EFIAPI efi_locate_protocol(const efi_guid_t *protocol, * Return: status code */ static efi_status_t EFIAPI efi_locate_device_path( - const efi_guid_t *protocol, + const efi_guid_t *protocol_guid, struct efi_device_path **device_path, efi_handle_t *device) { struct efi_device_path *dp; size_t i; + struct udevice *protocol; struct efi_handler *handler; efi_handle_t *handles; size_t len, len_dp; @@ -2291,9 +2483,9 @@ static efi_status_t EFIAPI efi_locate_device_path( u8 *remainder; efi_status_t ret;
- EFI_ENTRY("%pUl, %p, %p", protocol, device_path, device); + EFI_ENTRY("%pUl, %p, %p", protocol_guid, device_path, device);
- if (!protocol || !device_path || !*device_path || !device) { + if (!protocol_guid || !device_path || !*device_path || !device) { ret = EFI_INVALID_PARAMETER; goto out; } @@ -2302,17 +2494,19 @@ static efi_status_t EFIAPI efi_locate_device_path( len = efi_dp_instance_size(*device_path);
/* Get all handles implementing the protocol */ - ret = EFI_CALL(efi_locate_handle_buffer(BY_PROTOCOL, protocol, NULL, - &no_handles, &handles)); + ret = EFI_CALL(efi_locate_handle_buffer(BY_PROTOCOL, protocol_guid, + NULL, &no_handles, &handles)); if (ret != EFI_SUCCESS) goto out;
for (i = 0; i < no_handles; ++i) { /* Find the device path protocol */ ret = efi_search_protocol(handles[i], &efi_guid_device_path, - &handler); + &protocol); if (ret != EFI_SUCCESS) continue; + + handler = protocol->uclass_platdata; dp = (struct efi_device_path *)handler->protocol_interface; len_dp = efi_dp_instance_size(dp); /* @@ -2442,10 +2636,11 @@ static efi_status_t EFIAPI efi_uninstall_multiple_protocol_interfaces( efi_va_end(argptr); if (r == EFI_SUCCESS) { /* If the last protocol has been removed, delete the handle. */ - if (list_empty(&handle->protocols)) { - list_del(&handle->link); - free(handle); - } + if (device_find_first_child_by_uclass(handle, + UCLASS_EFI_PROTOCOL, + NULL)) + efi_remove_handle(handle); + return EFI_EXIT(r); }
@@ -2635,18 +2830,19 @@ out: * Return: status code */ static efi_status_t EFIAPI efi_open_protocol - (efi_handle_t handle, const efi_guid_t *protocol, + (efi_handle_t handle, const efi_guid_t *protocol_guid, void **protocol_interface, efi_handle_t agent_handle, efi_handle_t controller_handle, uint32_t attributes) { + struct udevice *protocol; struct efi_handler *handler; efi_status_t r = EFI_INVALID_PARAMETER;
- EFI_ENTRY("%p, %pUl, %p, %p, %p, 0x%x", handle, protocol, + EFI_ENTRY("%p, %pUl, %p, %p, %p, 0x%x", handle, protocol_guid, protocol_interface, agent_handle, controller_handle, attributes);
- if (!handle || !protocol || + if (!handle || !protocol_guid || (!protocol_interface && attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) { goto out; @@ -2663,23 +2859,26 @@ static efi_status_t EFIAPI efi_open_protocol /* fall-through */ case EFI_OPEN_PROTOCOL_BY_DRIVER: case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE: - /* Check that the controller handle is valid */ - if (!efi_search_obj(controller_handle)) + if (!efi_is_valid(controller_handle)) { + r = EFI_INVALID_PARAMETER; goto out; + } /* fall-through */ case EFI_OPEN_PROTOCOL_EXCLUSIVE: - /* Check that the agent handle is valid */ - if (!efi_search_obj(agent_handle)) + if (!efi_is_valid(agent_handle)) { + r = EFI_INVALID_PARAMETER; goto out; + } break; default: goto out; }
- r = efi_search_protocol(handle, protocol, &handler); + r = efi_search_protocol(handle, protocol_guid, &protocol); if (r != EFI_SUCCESS) goto out;
+ handler = protocol->uclass_platdata; r = efi_protocol_open(handler, protocol_interface, agent_handle, controller_handle, attributes); out: @@ -2839,18 +3038,16 @@ static efi_status_t EFIAPI efi_connect_controller( struct efi_device_path *remain_device_path, bool recursive) { + struct udevice *dev, *child; efi_status_t r; efi_status_t ret = EFI_NOT_FOUND; - struct efi_object *efiobj;
EFI_ENTRY("%p, %p, %p, %d", controller_handle, driver_image_handle, remain_device_path, recursive);
- efiobj = efi_search_obj(controller_handle); - if (!efiobj) { - ret = EFI_INVALID_PARAMETER; - goto out; - } + if (!efi_is_valid(controller_handle)) + return EFI_INVALID_PARAMETER; + dev = controller_handle;
r = efi_connect_single_controller(controller_handle, driver_image_handle, @@ -2861,7 +3058,11 @@ static efi_status_t EFIAPI efi_connect_controller( struct efi_handler *handler; struct efi_open_protocol_info_item *item;
- list_for_each_entry(handler, &efiobj->protocols, link) { + list_for_each_entry(child, &dev->child_head, sibling_node) { + if (child->driver->id != UCLASS_EFI_PROTOCOL) + continue; + + handler = child->uclass_platdata; list_for_each_entry(item, &handler->open_infos, link) { if (item->info.attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) { @@ -2880,7 +3081,7 @@ static efi_status_t EFIAPI efi_connect_controller( if (ret != EFI_SUCCESS && remain_device_path && remain_device_path->type == DEVICE_PATH_TYPE_END) ret = EFI_SUCCESS; -out: + return EFI_EXIT(ret); }
@@ -2945,18 +3146,23 @@ out: * Return: status code */ static efi_status_t efi_get_child_controllers( - struct efi_object *efiobj, + struct udevice *dev, efi_handle_t driver_handle, efi_uintn_t *number_of_children, efi_handle_t **child_handle_buffer) { + struct udevice *child; struct efi_handler *handler; struct efi_open_protocol_info_item *item; efi_uintn_t count = 0, i; bool duplicate;
/* Count all child controller associations */ - list_for_each_entry(handler, &efiobj->protocols, link) { + list_for_each_entry(child, &dev->child_head, sibling_node) { + if (child->driver->id != UCLASS_EFI_PROTOCOL) + continue; + + handler = child->uclass_platdata; list_for_each_entry(item, &handler->open_infos, link) { if (item->info.agent_handle == driver_handle && item->info.attributes & @@ -2973,7 +3179,11 @@ static efi_status_t efi_get_child_controllers( if (!*child_handle_buffer) return EFI_OUT_OF_RESOURCES; /* Copy unique child handles */ - list_for_each_entry(handler, &efiobj->protocols, link) { + list_for_each_entry(child, &dev->child_head, sibling_node) { + if (child->driver->id != UCLASS_EFI_PROTOCOL) + continue; + + handler = child->uclass_platdata; list_for_each_entry(item, &handler->open_infos, link) { if (item->info.agent_handle == driver_handle && item->info.attributes & @@ -3015,30 +3225,23 @@ static efi_status_t EFIAPI efi_disconnect_controller( efi_handle_t driver_image_handle, efi_handle_t child_handle) { + struct udevice *dev; struct efi_driver_binding_protocol *binding_protocol; efi_handle_t *child_handle_buffer = NULL; size_t number_of_children = 0; efi_status_t r; size_t stop_count = 0; - struct efi_object *efiobj;
EFI_ENTRY("%p, %p, %p", controller_handle, driver_image_handle, child_handle);
- efiobj = efi_search_obj(controller_handle); - if (!efiobj) { - r = EFI_INVALID_PARAMETER; - goto out; - } - - if (child_handle && !efi_search_obj(child_handle)) { - r = EFI_INVALID_PARAMETER; - goto out; - } + if (!efi_is_valid(controller_handle)) + return EFI_INVALID_PARAMETER; + dev = controller_handle;
/* If no driver handle is supplied, disconnect all drivers */ if (!driver_image_handle) { - r = efi_disconnect_all_drivers(efiobj, NULL, child_handle); + r = efi_disconnect_all_drivers(dev, NULL, child_handle); goto out; }
@@ -3047,7 +3250,7 @@ static efi_status_t EFIAPI efi_disconnect_controller( number_of_children = 1; child_handle_buffer = &child_handle; } else { - efi_get_child_controllers(efiobj, + efi_get_child_controllers(dev, driver_image_handle, &number_of_children, &child_handle_buffer); @@ -3186,3 +3389,30 @@ efi_status_t efi_initialize_system_table(void)
return ret; } + +/* + * UEFI object -- any device with no corresponding u-boot device + */ +U_BOOT_DRIVER(efi_dumb_obj) = { + .name = "efi_dumb_object", + .id = UCLASS_EFI_OBJECT, +}; + +UCLASS_DRIVER(efi_obj) = { + .name = "efi_object", + .id = UCLASS_EFI_OBJECT, +}; + +/* + * UEFI protocol + */ +U_BOOT_DRIVER(efi_protocol) = { + .name = "efi_protocol", + .id = UCLASS_EFI_PROTOCOL, +}; + +UCLASS_DRIVER(efi_protocol) = { + .name = "efi_protocol", + .id = UCLASS_EFI_PROTOCOL, + .per_device_platdata_auto_alloc_size = sizeof(struct efi_handler), +};

On 2/8/19 9:15 AM, AKASHI Takahiro wrote:
All efi objects are presented as DM devices, either existing device types or efi-specific, and efi_handle_t is an opaque pointer to "struct udevice."
We still maintain efi_obj_list as it is quite inefficient to traverse the DM hierarchy to find any efi objects, which are just part of it.
All efi protocols are also presented as DM devices, replacing "struct efi_handler" with "struct udevice." So searching for an efi protocol is nothing but traversing child nodes under a device.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
include/dm/device.h | 3 + include/dm/uclass-id.h | 2 + include/efi.h | 4 +- include/efi_loader.h | 37 +-- lib/efi_loader/efi_boottime.c | 544 ++++++++++++++++++++++++---------- 5 files changed, 400 insertions(+), 190 deletions(-)
diff --git a/include/dm/device.h b/include/dm/device.h index 27a6d7b9fdb0..0d82402c8e70 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -146,6 +146,9 @@ struct udevice { #ifdef CONFIG_DEVRES struct list_head devres_head; #endif +#ifdef CONFIG_EFI_LOADER
- void *efi_obj;
+#endif };
/* Maximum sequence number supported */ diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index f3bafb3c6353..fb0ab40891c8 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -40,6 +40,8 @@ enum uclass_id { UCLASS_DISPLAY, /* Display (e.g. DisplayPort, HDMI) */ UCLASS_DMA, /* Direct Memory Access */ UCLASS_EFI, /* EFI managed devices */
- UCLASS_EFI_OBJECT, /* EFI managed objects */
- UCLASS_EFI_PROTOCOL, /* EFI managed protocols */ UCLASS_ETH, /* Ethernet device */ UCLASS_FIRMWARE, /* Firmware */ UCLASS_FS_FIRMWARE_LOADER, /* Generic loader */
diff --git a/include/efi.h b/include/efi.h index b5e2c64f38b5..58902299a9a0 100644 --- a/include/efi.h +++ b/include/efi.h @@ -96,7 +96,9 @@ typedef struct { typedef unsigned long efi_status_t; typedef u64 efi_physical_addr_t; typedef u64 efi_virtual_addr_t; -typedef struct efi_object *efi_handle_t; +/* Eventually this should be 'void *' */ +struct udevice; +typedef struct udevice *efi_handle_t;
#define EFI_GUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \ {{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, \ diff --git a/include/efi_loader.h b/include/efi_loader.h index 3077a1e9d58b..4d5e22564a72 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -167,38 +167,12 @@ struct efi_open_protocol_info_item {
- protocol GUID to the respective protocol interface
*/ struct efi_handler {
- /* Link to the list of protocols of a handle */
- struct list_head link; const efi_guid_t *guid; void *protocol_interface; /* Link to the list of open protocol info items */ struct list_head open_infos;
};
-/**
- struct efi_object - dereferenced EFI handle
- @link: pointers to put the handle into a linked list
- @protocols: linked list with the protocol interfaces installed on this
handle
- UEFI offers a flexible and expandable object model. The objects in the UEFI
- API are devices, drivers, and loaded images. struct efi_object is our storage
- structure for these objects.
- When including this structure into a larger structure always put it first so
- that when deleting a handle the whole encompassing structure can be freed.
- A pointer to this structure is referred to as a handle. Typedef efi_handle_t
- has been created for such pointers.
- */
-struct efi_object {
- /* Every UEFI object is part of a global object list */
- struct list_head link;
- /* The list of protocols */
- struct list_head protocols;
-};
/**
- struct efi_loaded_image_obj - handle of a loaded image
@@ -209,7 +183,6 @@ struct efi_object {
- @entry: entry address of the relocated image
*/ struct efi_loaded_image_obj {
- struct efi_object header; void *reloc_base; aligned_u64 reloc_size; efi_status_t exit_status;
@@ -312,18 +285,18 @@ void efi_restore_gd(void); void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map); /* Call this to set the current device name */ void efi_set_bootdev(const char *dev, const char *devnr, const char *path); +/* Go through all the efi objects and call func() for each */ +efi_status_t efi_foreach_dev(int (*func)(struct udevice *, void *), void *arg); /* Add a new object to the object list. */ -void efi_add_handle(efi_handle_t obj); +efi_status_t efi_add_handle(struct udevice *dev); /* Create handle */ -efi_status_t efi_create_handle(efi_handle_t *handle); +efi_status_t efi_create_handle(efi_handle_t *handle, char *name); /* Delete handle */ void efi_delete_handle(efi_handle_t obj); -/* Call this to validate a handle and find the EFI object for it */ -struct efi_object *efi_search_obj(const efi_handle_t handle); /* Find a protocol on a handle */ efi_status_t efi_search_protocol(const efi_handle_t handle, const efi_guid_t *protocol_guid,
struct efi_handler **handler);
struct udevice **protocol);
/* Install new protocol on a handle */ efi_status_t efi_add_protocol(const efi_handle_t handle, const efi_guid_t *protocol, diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 291bc1bd35f9..d23e4fbbdf23 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -7,6 +7,10 @@
#include <common.h> #include <div64.h> +#include <dm.h> +#include <dm/device-internal.h> +#include <dm/lists.h> +#include <dm/root.h> #include <efi_loader.h> #include <environment.h> #include <malloc.h> @@ -17,6 +21,13 @@
DECLARE_GLOBAL_DATA_PTR;
+struct efi_object {
- /* Every UEFI object is part of a global object list */
- struct list_head link;
- /* The backing uclass device */
- struct udevice *dev;
+};
/* Task priority level */ static efi_uintn_t efi_tpl = TPL_APPLICATION;
@@ -418,70 +429,125 @@ static efi_status_t EFIAPI efi_free_pool_ext(void *buffer) return EFI_EXIT(r); }
+static bool efi_is_valid(efi_handle_t handle) +{
- struct efi_object *efiobj;
- list_for_each_entry(efiobj, &efi_obj_list, link) {
if (efiobj->dev == handle)
return true;
- }
- return false;
+}
+/**
- efi_foreach_dev()
- */
+efi_status_t efi_foreach_dev(int (*func)(struct udevice *, void *), void *arg) +{
- int ret;
- struct efi_object *efiobj;
- list_for_each_entry(efiobj, &efi_obj_list, link) {
ret = (*func)(efiobj->dev, arg);
if (ret == 1)
return EFI_SUCCESS;
- }
- return EFI_NOT_FOUND;
+}
/**
- efi_add_handle() - add a new object to the object list
- @obj: object to be added
*/
- @handle: udevice to be added as object
- The protocols list is initialized. The object handle is set.
-void efi_add_handle(efi_handle_t handle) +efi_status_t efi_add_handle(struct udevice *dev) {
- if (!handle)
return;
- INIT_LIST_HEAD(&handle->protocols);
- list_add_tail(&handle->link, &efi_obj_list);
- struct efi_object *efi_obj;
- if (!dev)
return EFI_INVALID_PARAMETER;
- efi_obj = calloc(1, sizeof(struct efi_object));
- if (!efi_obj)
return EFI_OUT_OF_RESOURCES;
- efi_obj->dev = dev;
- dev->efi_obj = efi_obj;
- list_add_tail(&efi_obj->link, &efi_obj_list);
- return EFI_SUCCESS;
}
/**
- efi_create_handle() - create handle
- @handle: new handle
*/
- @name: name
- Return: status code
-efi_status_t efi_create_handle(efi_handle_t *handle) +efi_status_t efi_create_handle(efi_handle_t *handle, char *name) {
- struct efi_object *obj;
- struct udevice *dev;
- efi_status_t ret;
- if (!handle)
return EFI_INVALID_PARAMETER;
- obj = calloc(1, sizeof(struct efi_object));
- if (!obj)
- ret = device_bind_driver(dm_root(), "efi_dumb_object", name, &dev);
In the EFI world the device tree is defined by the device tree protocol. Furthermore when a protocol is opened by a controller a relationship between device and controller is established.
Binding a new handle to dm_root disregards the logic of UEFI.
Think of an EFI application creating two handles via InstallProtocolInterface() with device paths /foo and /foo/bar. Next /foo/bar calls ConnectController() which causes /foo to open the protocol on /foo/bar as a controller.
With your code the handles would be siblings in the DM world while in the EFI world /foo is the parent of /foo/bar.
I suggest not to proceed into this direction.
Best regards
Heinrich
- if (ret) return EFI_OUT_OF_RESOURCES;
- efi_add_handle(obj);
- *handle = obj;
- ret = efi_add_handle(dev);
- if (ret)
+#ifdef CONFIG_DM_DEVICE_REMOVE
device_unbind(dev);
+#else
0;
+#endif
- else
*handle = dev;
- return EFI_SUCCESS;
- return ret;
}
/**
- efi_search_protocol() - find a protocol on a handle.
- @handle: handle
- @protocol_guid: GUID of the protocol
- @handler: reference to the protocol
*/
- @protocol: reference to the protocol
- Return: status code
efi_status_t efi_search_protocol(const efi_handle_t handle, const efi_guid_t *protocol_guid,
struct efi_handler **handler)
struct udevice **protocol)
{
- struct efi_object *efiobj;
- struct list_head *lhandle;
struct udevice *dev, *child;
struct efi_handler *handler;
if (!handle || !protocol_guid) return EFI_INVALID_PARAMETER;
- efiobj = efi_search_obj(handle);
- if (!efiobj)
- if (!efi_is_valid(handle)) return EFI_INVALID_PARAMETER;
- list_for_each(lhandle, &efiobj->protocols) {
struct efi_handler *protocol;
- dev = handle;
- list_for_each_entry(child, &dev->child_head, sibling_node) {
if (child->driver->id != UCLASS_EFI_PROTOCOL)
continue;
protocol = list_entry(lhandle, struct efi_handler, link);
if (!guidcmp(protocol->guid, protocol_guid)) {
if (handler)
*handler = protocol;
handler = child->uclass_platdata;
if (!guidcmp(handler->guid, protocol_guid)) {
if (protocol)
} }*protocol = child; return EFI_SUCCESS;
- return EFI_NOT_FOUND;
}
@@ -494,21 +560,33 @@ efi_status_t efi_search_protocol(const efi_handle_t handle,
- Return: status code
*/ efi_status_t efi_remove_protocol(const efi_handle_t handle,
const efi_guid_t *protocol,
const efi_guid_t *protocol_guid, void *protocol_interface)
{
- struct udevice *protocol; struct efi_handler *handler; efi_status_t ret;
- ret = efi_search_protocol(handle, protocol, &handler);
- ret = efi_search_protocol(handle, protocol_guid, &protocol); if (ret != EFI_SUCCESS) return ret;
- if (guidcmp(handler->guid, protocol))
- handler = protocol->uclass_platdata;
- if (guidcmp(handler->guid, protocol_guid)) return EFI_INVALID_PARAMETER;
- if (handler->protocol_interface != protocol_interface) return EFI_INVALID_PARAMETER;
+#if 1 /* FIXME */
- device_free(protocol);
+#ifdef CONFIG_DM_DEVICE_REMOVE
- device_unbind(protocol);
+#endif +#else list_del(&handler->link); free(handler); +#endif return EFI_SUCCESS; }
@@ -520,24 +598,46 @@ efi_status_t efi_remove_protocol(const efi_handle_t handle, */ efi_status_t efi_remove_all_protocols(const efi_handle_t handle) {
- struct efi_object *efiobj;
- struct efi_handler *protocol;
- struct efi_handler *pos;
- struct udevice *dev, *child, *pos;
- struct efi_handler *handler;
- efiobj = efi_search_obj(handle);
- if (!efiobj)
- if (!efi_is_valid(handle)) return EFI_INVALID_PARAMETER;
- list_for_each_entry_safe(protocol, pos, &efiobj->protocols, link) {
- dev = handle;
- list_for_each_entry_safe(child, pos, &dev->child_head, sibling_node) { efi_status_t ret;
ret = efi_remove_protocol(handle, protocol->guid,
protocol->protocol_interface);
if (child->driver->id != UCLASS_EFI_PROTOCOL)
continue;
handler = child->uclass_platdata;
ret = efi_remove_protocol(handle, handler->guid,
if (ret != EFI_SUCCESS) return ret; } return EFI_SUCCESS;handler->protocol_interface);
}
+static void efi_remove_handle(efi_handle_t handle) +{
- struct udevice *dev = handle;
- struct efi_object *efi_obj = dev->efi_obj;
- list_del(&efi_obj->link);
- free(efi_obj);
- /* free only if internal object */
- if (dev->driver->id == UCLASS_EFI_OBJECT) {
+#ifdef CONFIG_DM_DEVICE_REMOVE
device_unbind(dev);
+#endif
- }
- /* native device handle should be taken care of by caller */
+}
/**
- efi_delete_handle() - delete handle
@@ -547,9 +647,9 @@ void efi_delete_handle(efi_handle_t handle) { if (!handle) return;
- efi_remove_all_protocols(handle);
- list_del(&handle->link);
- free(handle);
- efi_remove_handle(handle);
}
/** @@ -923,24 +1023,6 @@ static efi_status_t EFIAPI efi_check_event(struct efi_event *event) return EFI_EXIT(EFI_NOT_READY); }
-/**
- efi_search_obj() - find the internal EFI object for a handle
- @handle: handle to find
- Return: EFI object
- */
-struct efi_object *efi_search_obj(const efi_handle_t handle) -{
- struct efi_object *efiobj;
- list_for_each_entry(efiobj, &efi_obj_list, link) {
if (efiobj == handle)
return efiobj;
- }
- return NULL;
-}
/**
- efi_open_protocol_info_entry() - create open protocol info entry and add it
to a protocol
@@ -976,6 +1058,88 @@ static efi_status_t efi_delete_open_info( return EFI_SUCCESS; }
+/* FIXME */ +extern const efi_guid_t efi_guid_text_input_ex_protocol; +extern const efi_guid_t efi_guid_text_input_protocol; +extern const efi_guid_t efi_guid_text_output_protocol; +extern const efi_guid_t efi_gop_guid; +extern const efi_guid_t efi_net_guid; +extern const efi_guid_t efi_pxe_guid;
+/* TODO: add entries one by one */ +static struct {
- const efi_guid_t *guid;
- const char *drv_name;
+} protocol_list[] = {
- {
.guid = &efi_guid_text_input_ex_protocol,
.drv_name = "efi_simple_text_input_ex",
- },
- {
.guid = &efi_guid_text_input_protocol,
.drv_name = "efi_simple_text_input",
- },
- {
.guid = &efi_guid_text_output_protocol,
.drv_name = "efi_simple_text_output",
- },
- {
.guid = &efi_guid_device_path,
.drv_name = "efi_device_path",
- },
- {
.guid = &efi_guid_device_path_to_text_protocol,
.drv_name = "efi_device_path_to_text",
- },
- {
.guid = &efi_guid_device_path_utilities_protocol,
.drv_name = "efi_device_path_utils",
- },
+#if defined(CONFIG_LCD) || defined(CONFIG_DM_VIDEO)
- {
.guid = &efi_gop_guid,
.drv_name = "efi_gop",
- },
+#endif +#if defined(CONFIG_NET)
- {
.guid = &efi_net_guid,
.drv_name = "efi_net",
- },
- {
.guid = &efi_net_guid,
.drv_name = "efi_pxe",
- },
+#endif
- {
.guid = &efi_guid_unicode_collation_protocol,
.drv_name = "efi_unicode_collation",
- },
- {
.guid = &efi_block_io_guid,
.drv_name = "efi_disk",
- },
- {
.guid = &efi_simple_file_system_protocol_guid,
.drv_name = "efi_simple_file_system",
- },
- {
.guid = &efi_guid_driver_binding_protocol,
.drv_name = "efi_driver_binding",
- },
+};
+static const char *get_protocol_drv_name(const efi_guid_t *guid) +{
- int i;
- for (i = 0; i < ARRAY_SIZE(protocol_list); i++)
if (!guidcmp(protocol_list[i].guid, guid))
return protocol_list[i].drv_name;
- return "efi_protocol";
+}
/**
- efi_add_protocol() - install new protocol on a handle
- @handle: handle on which the protocol shall be installed
@@ -985,28 +1149,36 @@ static efi_status_t efi_delete_open_info(
- Return: status code
*/ efi_status_t efi_add_protocol(const efi_handle_t handle,
const efi_guid_t *protocol,
const efi_guid_t *protocol_guid, void *protocol_interface)
{
- struct efi_object *efiobj;
- struct udevice *dev, *protocol; struct efi_handler *handler; efi_status_t ret;
- efiobj = efi_search_obj(handle);
- if (!efiobj)
- if (!efi_is_valid(handle)) return EFI_INVALID_PARAMETER;
- ret = efi_search_protocol(handle, protocol, NULL);
- dev = handle;
- ret = efi_search_protocol(handle, protocol_guid, NULL); if (ret != EFI_NOT_FOUND) return EFI_INVALID_PARAMETER;
- handler = calloc(1, sizeof(struct efi_handler));
- if (!handler)
- ret = device_bind_driver(dev, get_protocol_drv_name(protocol_guid),
"(PROTO)", &protocol);
- if (ret) return EFI_OUT_OF_RESOURCES;
- handler->guid = protocol;
- handler = protocol->uclass_platdata;
- handler->guid = protocol_guid; handler->protocol_interface = protocol_interface; INIT_LIST_HEAD(&handler->open_infos);
- list_add_tail(&handler->link, &efiobj->protocols);
- if (!guidcmp(&efi_guid_device_path, protocol))
- device_probe(protocol);
- if (!guidcmp(&efi_guid_device_path, protocol_guid)) EFI_PRINT("installed device path '%pD'\n", protocol_interface);
- return EFI_SUCCESS;
}
@@ -1042,7 +1214,7 @@ static efi_status_t EFIAPI efi_install_protocol_interface(
/* Create new handle if requested. */ if (!*handle) {
r = efi_create_handle(handle);
if (r != EFI_SUCCESS) goto out; debug("%sEFI: new handle %p\n", indent_string(nesting_level),r = efi_create_handle(handle, "(NO NAME)");
@@ -1073,13 +1245,20 @@ static efi_status_t efi_get_drivers(efi_handle_t handle, efi_uintn_t *number_of_drivers, efi_handle_t **driver_handle_buffer) {
struct udevice *dev, *child; struct efi_handler *handler; struct efi_open_protocol_info_item *item; efi_uintn_t count = 0, i; bool duplicate;
dev = handle;
/* Count all driver associations */
- list_for_each_entry(handler, &handle->protocols, link) {
- list_for_each_entry(child, &dev->child_head, sibling_node) {
if (child->driver->id != UCLASS_EFI_PROTOCOL)
continue;
if (protocol && guidcmp(handler->guid, protocol)) continue; list_for_each_entry(item, &handler->open_infos, link) {handler = child->uclass_platdata;
@@ -1097,7 +1276,11 @@ static efi_status_t efi_get_drivers(efi_handle_t handle, if (!*driver_handle_buffer) return EFI_OUT_OF_RESOURCES; /* Collect unique driver handles */
- list_for_each_entry(handler, &handle->protocols, link) {
- list_for_each_entry(child, &dev->child_head, sibling_node) {
if (child->driver->id != UCLASS_EFI_PROTOCOL)
continue;
if (protocol && guidcmp(handler->guid, protocol)) continue; list_for_each_entry(item, &handler->open_infos, link) {handler = child->uclass_platdata;
@@ -1173,28 +1356,27 @@ static efi_status_t efi_disconnect_all_drivers
- Return: status code
*/ -static efi_status_t efi_uninstall_protocol
(efi_handle_t handle, const efi_guid_t *protocol,
void *protocol_interface)
+static efi_status_t efi_uninstall_protocol(efi_handle_t handle,
const efi_guid_t *protocol_guid,
void *protocol_interface)
{
- struct efi_object *efiobj;
- struct udevice *protocol; struct efi_handler *handler; struct efi_open_protocol_info_item *item; struct efi_open_protocol_info_item *pos; efi_status_t r;
- /* Check handle */
- efiobj = efi_search_obj(handle);
- if (!efiobj) {
r = EFI_INVALID_PARAMETER;
goto out;
- }
- if (!efi_is_valid(handle))
return EFI_INVALID_PARAMETER;
- /* Find the protocol on the handle */
- r = efi_search_protocol(handle, protocol, &handler);
- r = efi_search_protocol(handle, protocol_guid, &protocol); if (r != EFI_SUCCESS) goto out;
- handler = protocol->uclass_platdata;
- /* Disconnect controllers */
- efi_disconnect_all_drivers(efiobj, protocol, NULL);
- efi_disconnect_all_drivers(handle, protocol_guid, NULL); if (!list_empty(&handler->open_infos)) { r = EFI_ACCESS_DENIED; goto out;
@@ -1211,7 +1393,7 @@ static efi_status_t efi_uninstall_protocol r = EFI_ACCESS_DENIED; goto out; }
- r = efi_remove_protocol(handle, protocol, protocol_interface);
- r = efi_remove_protocol(handle, protocol_guid, protocol_interface);
out: return r; } @@ -1242,10 +1424,9 @@ static efi_status_t EFIAPI efi_uninstall_protocol_interface goto out;
/* If the last protocol has been removed, delete the handle. */
- if (list_empty(&handle->protocols)) {
list_del(&handle->link);
free(handle);
- }
- if (device_find_first_child_by_uclass(handle, UCLASS_EFI_PROTOCOL,
NULL))
efi_remove_handle(handle);
out: return EFI_EXIT(ret); } @@ -1352,7 +1533,7 @@ static efi_status_t efi_locate_handle(
/* Count how much space we need */ list_for_each_entry(efiobj, &efi_obj_list, link) {
if (!efi_search(search_type, protocol, search_key, efiobj))
}if (!efi_search(search_type, protocol, search_key, efiobj->dev)) size += sizeof(void *);
@@ -1367,8 +1548,8 @@ static efi_status_t efi_locate_handle(
/* Then fill the array */ list_for_each_entry(efiobj, &efi_obj_list, link) {
if (!efi_search(search_type, protocol, search_key, efiobj))
*buffer++ = efiobj;
if (!efi_search(search_type, protocol, search_key, efiobj->dev))
*buffer++ = efiobj->dev;
}
return EFI_SUCCESS;
@@ -2012,25 +2193,27 @@ static efi_status_t EFIAPI efi_set_watchdog_timer(unsigned long timeout,
- Return: status code
*/ static efi_status_t EFIAPI efi_close_protocol(efi_handle_t handle,
const efi_guid_t *protocol,
const efi_guid_t *protocol_guid, efi_handle_t agent_handle, efi_handle_t controller_handle)
{
- struct udevice *protocol; struct efi_handler *handler; struct efi_open_protocol_info_item *item; struct efi_open_protocol_info_item *pos; efi_status_t r;
- EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, agent_handle,
EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol_guid, agent_handle, controller_handle);
if (!agent_handle) { r = EFI_INVALID_PARAMETER; goto out; }
- r = efi_search_protocol(handle, protocol, &handler);
r = efi_search_protocol(handle, protocol_guid, &protocol); if (r != EFI_SUCCESS) goto out;
handler = protocol->uclass_platdata;
r = EFI_NOT_FOUND; list_for_each_entry_safe(item, pos, &handler->open_infos, link) {
@@ -2061,17 +2244,18 @@ out:
- Return: status code
*/ static efi_status_t EFIAPI efi_open_protocol_information(
efi_handle_t handle, const efi_guid_t *protocol,
efi_handle_t handle, const efi_guid_t *protocol_guid, struct efi_open_protocol_info_entry **entry_buffer, efi_uintn_t *entry_count)
{ unsigned long buffer_size; unsigned long count;
- struct udevice *protocol; struct efi_handler *handler; struct efi_open_protocol_info_item *item; efi_status_t r;
- EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, entry_buffer,
EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol_guid, entry_buffer, entry_count);
/* Check parameters */
@@ -2079,9 +2263,10 @@ static efi_status_t EFIAPI efi_open_protocol_information( r = EFI_INVALID_PARAMETER; goto out; }
- r = efi_search_protocol(handle, protocol, &handler);
r = efi_search_protocol(handle, protocol_guid, &protocol); if (r != EFI_SUCCESS) goto out;
handler = protocol->uclass_platdata;
/* Count entries */ count = 0;
@@ -2127,9 +2312,8 @@ static efi_status_t EFIAPI efi_protocols_per_handle( efi_handle_t handle, efi_guid_t ***protocol_buffer, efi_uintn_t *protocol_buffer_count) {
- struct udevice *dev, *child; unsigned long buffer_size;
struct efi_object *efiobj;
struct list_head *protocol_handle; efi_status_t r;
EFI_ENTRY("%p, %p, %p", handle, protocol_buffer,
@@ -2141,12 +2325,15 @@ static efi_status_t EFIAPI efi_protocols_per_handle( *protocol_buffer = NULL; *protocol_buffer_count = 0;
- efiobj = efi_search_obj(handle);
- if (!efiobj)
return EFI_EXIT(EFI_INVALID_PARAMETER);
if (!efi_is_valid(handle))
return EFI_INVALID_PARAMETER;
dev = handle;
/* Count protocols */
- list_for_each(protocol_handle, &efiobj->protocols) {
- list_for_each_entry(child, &dev->child_head, sibling_node) {
if (child->driver->id != UCLASS_EFI_PROTOCOL)
continue;
- ++*protocol_buffer_count; }
@@ -2159,12 +2346,15 @@ static efi_status_t EFIAPI efi_protocols_per_handle( (void **)protocol_buffer); if (r != EFI_SUCCESS) return EFI_EXIT(r);
list_for_each(protocol_handle, &efiobj->protocols) {
struct efi_handler *protocol;
protocol = list_entry(protocol_handle,
struct efi_handler, link);
(*protocol_buffer)[j] = (void *)protocol->guid;
list_for_each_entry(child, &dev->child_head, sibling_node) {
struct efi_handler *handler;
if (child->driver->id != UCLASS_EFI_PROTOCOL)
continue;
handler = child->uclass_platdata;
} }(*protocol_buffer)[j] = (void *)handler->guid; ++j;
@@ -2233,26 +2423,27 @@ out:
- Return: status code
*/ -static efi_status_t EFIAPI efi_locate_protocol(const efi_guid_t *protocol, +static efi_status_t EFIAPI efi_locate_protocol(const efi_guid_t *protocol_guid, void *registration, void **protocol_interface) {
- struct list_head *lhandle;
- struct efi_object *efiobj; efi_status_t ret;
- EFI_ENTRY("%pUl, %p, %p", protocol, registration, protocol_interface);
- EFI_ENTRY("%pUl, %p, %p", protocol_guid, registration,
protocol_interface);
- if (!protocol || !protocol_interface)
- if (!protocol_guid || !protocol_interface) return EFI_EXIT(EFI_INVALID_PARAMETER);
- list_for_each(lhandle, &efi_obj_list) {
struct efi_object *efiobj;
- list_for_each_entry(efiobj, &efi_obj_list, link) { struct efi_handler *handler;
struct udevice *protocol;
efiobj = list_entry(lhandle, struct efi_object, link);
ret = efi_search_protocol(efiobj, protocol, &handler);
ret = efi_search_protocol(efiobj->dev, protocol_guid,
if (ret == EFI_SUCCESS) {&protocol);
}handler = protocol->uclass_platdata; *protocol_interface = handler->protocol_interface; return EFI_EXIT(EFI_SUCCESS);
@@ -2277,12 +2468,13 @@ static efi_status_t EFIAPI efi_locate_protocol(const efi_guid_t *protocol,
- Return: status code
*/ static efi_status_t EFIAPI efi_locate_device_path(
const efi_guid_t *protocol,
const efi_guid_t *protocol_guid, struct efi_device_path **device_path, efi_handle_t *device)
{ struct efi_device_path *dp; size_t i;
- struct udevice *protocol; struct efi_handler *handler; efi_handle_t *handles; size_t len, len_dp;
@@ -2291,9 +2483,9 @@ static efi_status_t EFIAPI efi_locate_device_path( u8 *remainder; efi_status_t ret;
- EFI_ENTRY("%pUl, %p, %p", protocol, device_path, device);
- EFI_ENTRY("%pUl, %p, %p", protocol_guid, device_path, device);
- if (!protocol || !device_path || !*device_path || !device) {
- if (!protocol_guid || !device_path || !*device_path || !device) { ret = EFI_INVALID_PARAMETER; goto out; }
@@ -2302,17 +2494,19 @@ static efi_status_t EFIAPI efi_locate_device_path( len = efi_dp_instance_size(*device_path);
/* Get all handles implementing the protocol */
- ret = EFI_CALL(efi_locate_handle_buffer(BY_PROTOCOL, protocol, NULL,
&no_handles, &handles));
ret = EFI_CALL(efi_locate_handle_buffer(BY_PROTOCOL, protocol_guid,
NULL, &no_handles, &handles));
if (ret != EFI_SUCCESS) goto out;
for (i = 0; i < no_handles; ++i) { /* Find the device path protocol */ ret = efi_search_protocol(handles[i], &efi_guid_device_path,
&handler);
if (ret != EFI_SUCCESS) continue;&protocol);
dp = (struct efi_device_path *)handler->protocol_interface; len_dp = efi_dp_instance_size(dp); /*handler = protocol->uclass_platdata;
@@ -2442,10 +2636,11 @@ static efi_status_t EFIAPI efi_uninstall_multiple_protocol_interfaces( efi_va_end(argptr); if (r == EFI_SUCCESS) { /* If the last protocol has been removed, delete the handle. */
if (list_empty(&handle->protocols)) {
list_del(&handle->link);
free(handle);
}
if (device_find_first_child_by_uclass(handle,
UCLASS_EFI_PROTOCOL,
NULL))
efi_remove_handle(handle);
- return EFI_EXIT(r); }
@@ -2635,18 +2830,19 @@ out:
- Return: status code
*/ static efi_status_t EFIAPI efi_open_protocol
(efi_handle_t handle, const efi_guid_t *protocol,
(efi_handle_t handle, const efi_guid_t *protocol_guid, void **protocol_interface, efi_handle_t agent_handle, efi_handle_t controller_handle, uint32_t attributes)
{
- struct udevice *protocol; struct efi_handler *handler; efi_status_t r = EFI_INVALID_PARAMETER;
- EFI_ENTRY("%p, %pUl, %p, %p, %p, 0x%x", handle, protocol,
- EFI_ENTRY("%p, %pUl, %p, %p, %p, 0x%x", handle, protocol_guid, protocol_interface, agent_handle, controller_handle, attributes);
- if (!handle || !protocol ||
- if (!handle || !protocol_guid || (!protocol_interface && attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) { goto out;
@@ -2663,23 +2859,26 @@ static efi_status_t EFIAPI efi_open_protocol /* fall-through */ case EFI_OPEN_PROTOCOL_BY_DRIVER: case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE:
/* Check that the controller handle is valid */
if (!efi_search_obj(controller_handle))
if (!efi_is_valid(controller_handle)) {
r = EFI_INVALID_PARAMETER; goto out;
/* fall-through */ case EFI_OPEN_PROTOCOL_EXCLUSIVE:}
/* Check that the agent handle is valid */
if (!efi_search_obj(agent_handle))
if (!efi_is_valid(agent_handle)) {
r = EFI_INVALID_PARAMETER; goto out;
break; default: goto out; }}
- r = efi_search_protocol(handle, protocol, &handler);
r = efi_search_protocol(handle, protocol_guid, &protocol); if (r != EFI_SUCCESS) goto out;
handler = protocol->uclass_platdata; r = efi_protocol_open(handler, protocol_interface, agent_handle, controller_handle, attributes);
out: @@ -2839,18 +3038,16 @@ static efi_status_t EFIAPI efi_connect_controller( struct efi_device_path *remain_device_path, bool recursive) {
- struct udevice *dev, *child; efi_status_t r; efi_status_t ret = EFI_NOT_FOUND;
struct efi_object *efiobj;
EFI_ENTRY("%p, %p, %p, %d", controller_handle, driver_image_handle, remain_device_path, recursive);
efiobj = efi_search_obj(controller_handle);
if (!efiobj) {
ret = EFI_INVALID_PARAMETER;
goto out;
}
if (!efi_is_valid(controller_handle))
return EFI_INVALID_PARAMETER;
dev = controller_handle;
r = efi_connect_single_controller(controller_handle, driver_image_handle,
@@ -2861,7 +3058,11 @@ static efi_status_t EFIAPI efi_connect_controller( struct efi_handler *handler; struct efi_open_protocol_info_item *item;
list_for_each_entry(handler, &efiobj->protocols, link) {
list_for_each_entry(child, &dev->child_head, sibling_node) {
if (child->driver->id != UCLASS_EFI_PROTOCOL)
continue;
handler = child->uclass_platdata; list_for_each_entry(item, &handler->open_infos, link) { if (item->info.attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
@@ -2880,7 +3081,7 @@ static efi_status_t EFIAPI efi_connect_controller( if (ret != EFI_SUCCESS && remain_device_path && remain_device_path->type == DEVICE_PATH_TYPE_END) ret = EFI_SUCCESS; -out:
- return EFI_EXIT(ret);
}
@@ -2945,18 +3146,23 @@ out:
- Return: status code
*/ static efi_status_t efi_get_child_controllers(
struct efi_object *efiobj,
struct udevice *dev, efi_handle_t driver_handle, efi_uintn_t *number_of_children, efi_handle_t **child_handle_buffer)
{
struct udevice *child; struct efi_handler *handler; struct efi_open_protocol_info_item *item; efi_uintn_t count = 0, i; bool duplicate;
/* Count all child controller associations */
- list_for_each_entry(handler, &efiobj->protocols, link) {
- list_for_each_entry(child, &dev->child_head, sibling_node) {
if (child->driver->id != UCLASS_EFI_PROTOCOL)
continue;
list_for_each_entry(item, &handler->open_infos, link) { if (item->info.agent_handle == driver_handle && item->info.attributes &handler = child->uclass_platdata;
@@ -2973,7 +3179,11 @@ static efi_status_t efi_get_child_controllers( if (!*child_handle_buffer) return EFI_OUT_OF_RESOURCES; /* Copy unique child handles */
- list_for_each_entry(handler, &efiobj->protocols, link) {
- list_for_each_entry(child, &dev->child_head, sibling_node) {
if (child->driver->id != UCLASS_EFI_PROTOCOL)
continue;
list_for_each_entry(item, &handler->open_infos, link) { if (item->info.agent_handle == driver_handle && item->info.attributes &handler = child->uclass_platdata;
@@ -3015,30 +3225,23 @@ static efi_status_t EFIAPI efi_disconnect_controller( efi_handle_t driver_image_handle, efi_handle_t child_handle) {
- struct udevice *dev; struct efi_driver_binding_protocol *binding_protocol; efi_handle_t *child_handle_buffer = NULL; size_t number_of_children = 0; efi_status_t r; size_t stop_count = 0;
struct efi_object *efiobj;
EFI_ENTRY("%p, %p, %p", controller_handle, driver_image_handle, child_handle);
efiobj = efi_search_obj(controller_handle);
if (!efiobj) {
r = EFI_INVALID_PARAMETER;
goto out;
}
if (child_handle && !efi_search_obj(child_handle)) {
r = EFI_INVALID_PARAMETER;
goto out;
}
if (!efi_is_valid(controller_handle))
return EFI_INVALID_PARAMETER;
dev = controller_handle;
/* If no driver handle is supplied, disconnect all drivers */ if (!driver_image_handle) {
r = efi_disconnect_all_drivers(efiobj, NULL, child_handle);
goto out; }r = efi_disconnect_all_drivers(dev, NULL, child_handle);
@@ -3047,7 +3250,7 @@ static efi_status_t EFIAPI efi_disconnect_controller( number_of_children = 1; child_handle_buffer = &child_handle; } else {
efi_get_child_controllers(efiobj,
efi_get_child_controllers(dev, driver_image_handle, &number_of_children, &child_handle_buffer);
@@ -3186,3 +3389,30 @@ efi_status_t efi_initialize_system_table(void)
return ret; }
+/*
- UEFI object -- any device with no corresponding u-boot device
- */
+U_BOOT_DRIVER(efi_dumb_obj) = {
- .name = "efi_dumb_object",
- .id = UCLASS_EFI_OBJECT,
+};
+UCLASS_DRIVER(efi_obj) = {
- .name = "efi_object",
- .id = UCLASS_EFI_OBJECT,
+};
+/*
- UEFI protocol
- */
+U_BOOT_DRIVER(efi_protocol) = {
- .name = "efi_protocol",
- .id = UCLASS_EFI_PROTOCOL,
+};
+UCLASS_DRIVER(efi_protocol) = {
- .name = "efi_protocol",
- .id = UCLASS_EFI_PROTOCOL,
- .per_device_platdata_auto_alloc_size = sizeof(struct efi_handler),
+};

Heinrich,
On Fri, Feb 08, 2019 at 06:47:12PM +0100, Heinrich Schuchardt wrote:
On 2/8/19 9:15 AM, AKASHI Takahiro wrote:
All efi objects are presented as DM devices, either existing device types or efi-specific, and efi_handle_t is an opaque pointer to "struct udevice."
We still maintain efi_obj_list as it is quite inefficient to traverse the DM hierarchy to find any efi objects, which are just part of it.
All efi protocols are also presented as DM devices, replacing "struct efi_handler" with "struct udevice." So searching for an efi protocol is nothing but traversing child nodes under a device.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
include/dm/device.h | 3 + include/dm/uclass-id.h | 2 + include/efi.h | 4 +- include/efi_loader.h | 37 +-- lib/efi_loader/efi_boottime.c | 544 ++++++++++++++++++++++++---------- 5 files changed, 400 insertions(+), 190 deletions(-)
diff --git a/include/dm/device.h b/include/dm/device.h index 27a6d7b9fdb0..0d82402c8e70 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -146,6 +146,9 @@ struct udevice { #ifdef CONFIG_DEVRES struct list_head devres_head; #endif +#ifdef CONFIG_EFI_LOADER
- void *efi_obj;
+#endif };
/* Maximum sequence number supported */ diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index f3bafb3c6353..fb0ab40891c8 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -40,6 +40,8 @@ enum uclass_id { UCLASS_DISPLAY, /* Display (e.g. DisplayPort, HDMI) */ UCLASS_DMA, /* Direct Memory Access */ UCLASS_EFI, /* EFI managed devices */
- UCLASS_EFI_OBJECT, /* EFI managed objects */
- UCLASS_EFI_PROTOCOL, /* EFI managed protocols */ UCLASS_ETH, /* Ethernet device */ UCLASS_FIRMWARE, /* Firmware */ UCLASS_FS_FIRMWARE_LOADER, /* Generic loader */
diff --git a/include/efi.h b/include/efi.h index b5e2c64f38b5..58902299a9a0 100644 --- a/include/efi.h +++ b/include/efi.h @@ -96,7 +96,9 @@ typedef struct { typedef unsigned long efi_status_t; typedef u64 efi_physical_addr_t; typedef u64 efi_virtual_addr_t; -typedef struct efi_object *efi_handle_t; +/* Eventually this should be 'void *' */ +struct udevice; +typedef struct udevice *efi_handle_t;
#define EFI_GUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \ {{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, \ diff --git a/include/efi_loader.h b/include/efi_loader.h index 3077a1e9d58b..4d5e22564a72 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -167,38 +167,12 @@ struct efi_open_protocol_info_item {
- protocol GUID to the respective protocol interface
*/ struct efi_handler {
- /* Link to the list of protocols of a handle */
- struct list_head link; const efi_guid_t *guid; void *protocol_interface; /* Link to the list of open protocol info items */ struct list_head open_infos;
};
-/**
- struct efi_object - dereferenced EFI handle
- @link: pointers to put the handle into a linked list
- @protocols: linked list with the protocol interfaces installed on this
handle
- UEFI offers a flexible and expandable object model. The objects in the UEFI
- API are devices, drivers, and loaded images. struct efi_object is our storage
- structure for these objects.
- When including this structure into a larger structure always put it first so
- that when deleting a handle the whole encompassing structure can be freed.
- A pointer to this structure is referred to as a handle. Typedef efi_handle_t
- has been created for such pointers.
- */
-struct efi_object {
- /* Every UEFI object is part of a global object list */
- struct list_head link;
- /* The list of protocols */
- struct list_head protocols;
-};
/**
- struct efi_loaded_image_obj - handle of a loaded image
@@ -209,7 +183,6 @@ struct efi_object {
- @entry: entry address of the relocated image
*/ struct efi_loaded_image_obj {
- struct efi_object header; void *reloc_base; aligned_u64 reloc_size; efi_status_t exit_status;
@@ -312,18 +285,18 @@ void efi_restore_gd(void); void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map); /* Call this to set the current device name */ void efi_set_bootdev(const char *dev, const char *devnr, const char *path); +/* Go through all the efi objects and call func() for each */ +efi_status_t efi_foreach_dev(int (*func)(struct udevice *, void *), void *arg); /* Add a new object to the object list. */ -void efi_add_handle(efi_handle_t obj); +efi_status_t efi_add_handle(struct udevice *dev); /* Create handle */ -efi_status_t efi_create_handle(efi_handle_t *handle); +efi_status_t efi_create_handle(efi_handle_t *handle, char *name); /* Delete handle */ void efi_delete_handle(efi_handle_t obj); -/* Call this to validate a handle and find the EFI object for it */ -struct efi_object *efi_search_obj(const efi_handle_t handle); /* Find a protocol on a handle */ efi_status_t efi_search_protocol(const efi_handle_t handle, const efi_guid_t *protocol_guid,
struct efi_handler **handler);
struct udevice **protocol);
/* Install new protocol on a handle */ efi_status_t efi_add_protocol(const efi_handle_t handle, const efi_guid_t *protocol, diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 291bc1bd35f9..d23e4fbbdf23 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -7,6 +7,10 @@
#include <common.h> #include <div64.h> +#include <dm.h> +#include <dm/device-internal.h> +#include <dm/lists.h> +#include <dm/root.h> #include <efi_loader.h> #include <environment.h> #include <malloc.h> @@ -17,6 +21,13 @@
DECLARE_GLOBAL_DATA_PTR;
+struct efi_object {
- /* Every UEFI object is part of a global object list */
- struct list_head link;
- /* The backing uclass device */
- struct udevice *dev;
+};
/* Task priority level */ static efi_uintn_t efi_tpl = TPL_APPLICATION;
@@ -418,70 +429,125 @@ static efi_status_t EFIAPI efi_free_pool_ext(void *buffer) return EFI_EXIT(r); }
+static bool efi_is_valid(efi_handle_t handle) +{
- struct efi_object *efiobj;
- list_for_each_entry(efiobj, &efi_obj_list, link) {
if (efiobj->dev == handle)
return true;
- }
- return false;
+}
+/**
- efi_foreach_dev()
- */
+efi_status_t efi_foreach_dev(int (*func)(struct udevice *, void *), void *arg) +{
- int ret;
- struct efi_object *efiobj;
- list_for_each_entry(efiobj, &efi_obj_list, link) {
ret = (*func)(efiobj->dev, arg);
if (ret == 1)
return EFI_SUCCESS;
- }
- return EFI_NOT_FOUND;
+}
/**
- efi_add_handle() - add a new object to the object list
- @obj: object to be added
*/
- @handle: udevice to be added as object
- The protocols list is initialized. The object handle is set.
-void efi_add_handle(efi_handle_t handle) +efi_status_t efi_add_handle(struct udevice *dev) {
- if (!handle)
return;
- INIT_LIST_HEAD(&handle->protocols);
- list_add_tail(&handle->link, &efi_obj_list);
- struct efi_object *efi_obj;
- if (!dev)
return EFI_INVALID_PARAMETER;
- efi_obj = calloc(1, sizeof(struct efi_object));
- if (!efi_obj)
return EFI_OUT_OF_RESOURCES;
- efi_obj->dev = dev;
- dev->efi_obj = efi_obj;
- list_add_tail(&efi_obj->link, &efi_obj_list);
- return EFI_SUCCESS;
}
/**
- efi_create_handle() - create handle
- @handle: new handle
*/
- @name: name
- Return: status code
-efi_status_t efi_create_handle(efi_handle_t *handle) +efi_status_t efi_create_handle(efi_handle_t *handle, char *name) {
- struct efi_object *obj;
- struct udevice *dev;
- efi_status_t ret;
- if (!handle)
return EFI_INVALID_PARAMETER;
- obj = calloc(1, sizeof(struct efi_object));
- if (!obj)
- ret = device_bind_driver(dm_root(), "efi_dumb_object", name, &dev);
In the EFI world the device tree is defined by the device tree protocol.
device tree -> device path?
Furthermore when a protocol is opened by a controller a relationship between device and controller is established.
Binding a new handle to dm_root disregards the logic of UEFI.
Think of an EFI application creating two handles via InstallProtocolInterface() with device paths /foo and /foo/bar. Next /foo/bar calls ConnectController() which causes /foo to open the protocol on /foo/bar as a controller.
Can you give me a concrete example of foo and baa here so that I can understand you more precisely?
With your code the handles would be siblings in the DM world while in the EFI world /foo is the parent of /foo/bar.
Then, DM tree would not be static. We will be able to relocate /foo/bar under /foo to match such a device path with DM tree?
Thanks, -Takahiro Akashi
I suggest not to proceed into this direction.
Best regards
Heinrich
- if (ret) return EFI_OUT_OF_RESOURCES;
- efi_add_handle(obj);
- *handle = obj;
- ret = efi_add_handle(dev);
- if (ret)
+#ifdef CONFIG_DM_DEVICE_REMOVE
device_unbind(dev);
+#else
0;
+#endif
- else
*handle = dev;
- return EFI_SUCCESS;
- return ret;
}
/**
- efi_search_protocol() - find a protocol on a handle.
- @handle: handle
- @protocol_guid: GUID of the protocol
- @handler: reference to the protocol
*/
- @protocol: reference to the protocol
- Return: status code
efi_status_t efi_search_protocol(const efi_handle_t handle, const efi_guid_t *protocol_guid,
struct efi_handler **handler)
struct udevice **protocol)
{
- struct efi_object *efiobj;
- struct list_head *lhandle;
struct udevice *dev, *child;
struct efi_handler *handler;
if (!handle || !protocol_guid) return EFI_INVALID_PARAMETER;
- efiobj = efi_search_obj(handle);
- if (!efiobj)
- if (!efi_is_valid(handle)) return EFI_INVALID_PARAMETER;
- list_for_each(lhandle, &efiobj->protocols) {
struct efi_handler *protocol;
- dev = handle;
- list_for_each_entry(child, &dev->child_head, sibling_node) {
if (child->driver->id != UCLASS_EFI_PROTOCOL)
continue;
protocol = list_entry(lhandle, struct efi_handler, link);
if (!guidcmp(protocol->guid, protocol_guid)) {
if (handler)
*handler = protocol;
handler = child->uclass_platdata;
if (!guidcmp(handler->guid, protocol_guid)) {
if (protocol)
} }*protocol = child; return EFI_SUCCESS;
- return EFI_NOT_FOUND;
}
@@ -494,21 +560,33 @@ efi_status_t efi_search_protocol(const efi_handle_t handle,
- Return: status code
*/ efi_status_t efi_remove_protocol(const efi_handle_t handle,
const efi_guid_t *protocol,
const efi_guid_t *protocol_guid, void *protocol_interface)
{
- struct udevice *protocol; struct efi_handler *handler; efi_status_t ret;
- ret = efi_search_protocol(handle, protocol, &handler);
- ret = efi_search_protocol(handle, protocol_guid, &protocol); if (ret != EFI_SUCCESS) return ret;
- if (guidcmp(handler->guid, protocol))
- handler = protocol->uclass_platdata;
- if (guidcmp(handler->guid, protocol_guid)) return EFI_INVALID_PARAMETER;
- if (handler->protocol_interface != protocol_interface) return EFI_INVALID_PARAMETER;
+#if 1 /* FIXME */
- device_free(protocol);
+#ifdef CONFIG_DM_DEVICE_REMOVE
- device_unbind(protocol);
+#endif +#else list_del(&handler->link); free(handler); +#endif return EFI_SUCCESS; }
@@ -520,24 +598,46 @@ efi_status_t efi_remove_protocol(const efi_handle_t handle, */ efi_status_t efi_remove_all_protocols(const efi_handle_t handle) {
- struct efi_object *efiobj;
- struct efi_handler *protocol;
- struct efi_handler *pos;
- struct udevice *dev, *child, *pos;
- struct efi_handler *handler;
- efiobj = efi_search_obj(handle);
- if (!efiobj)
- if (!efi_is_valid(handle)) return EFI_INVALID_PARAMETER;
- list_for_each_entry_safe(protocol, pos, &efiobj->protocols, link) {
- dev = handle;
- list_for_each_entry_safe(child, pos, &dev->child_head, sibling_node) { efi_status_t ret;
ret = efi_remove_protocol(handle, protocol->guid,
protocol->protocol_interface);
if (child->driver->id != UCLASS_EFI_PROTOCOL)
continue;
handler = child->uclass_platdata;
ret = efi_remove_protocol(handle, handler->guid,
if (ret != EFI_SUCCESS) return ret; } return EFI_SUCCESS;handler->protocol_interface);
}
+static void efi_remove_handle(efi_handle_t handle) +{
- struct udevice *dev = handle;
- struct efi_object *efi_obj = dev->efi_obj;
- list_del(&efi_obj->link);
- free(efi_obj);
- /* free only if internal object */
- if (dev->driver->id == UCLASS_EFI_OBJECT) {
+#ifdef CONFIG_DM_DEVICE_REMOVE
device_unbind(dev);
+#endif
- }
- /* native device handle should be taken care of by caller */
+}
/**
- efi_delete_handle() - delete handle
@@ -547,9 +647,9 @@ void efi_delete_handle(efi_handle_t handle) { if (!handle) return;
- efi_remove_all_protocols(handle);
- list_del(&handle->link);
- free(handle);
- efi_remove_handle(handle);
}
/** @@ -923,24 +1023,6 @@ static efi_status_t EFIAPI efi_check_event(struct efi_event *event) return EFI_EXIT(EFI_NOT_READY); }
-/**
- efi_search_obj() - find the internal EFI object for a handle
- @handle: handle to find
- Return: EFI object
- */
-struct efi_object *efi_search_obj(const efi_handle_t handle) -{
- struct efi_object *efiobj;
- list_for_each_entry(efiobj, &efi_obj_list, link) {
if (efiobj == handle)
return efiobj;
- }
- return NULL;
-}
/**
- efi_open_protocol_info_entry() - create open protocol info entry and add it
to a protocol
@@ -976,6 +1058,88 @@ static efi_status_t efi_delete_open_info( return EFI_SUCCESS; }
+/* FIXME */ +extern const efi_guid_t efi_guid_text_input_ex_protocol; +extern const efi_guid_t efi_guid_text_input_protocol; +extern const efi_guid_t efi_guid_text_output_protocol; +extern const efi_guid_t efi_gop_guid; +extern const efi_guid_t efi_net_guid; +extern const efi_guid_t efi_pxe_guid;
+/* TODO: add entries one by one */ +static struct {
- const efi_guid_t *guid;
- const char *drv_name;
+} protocol_list[] = {
- {
.guid = &efi_guid_text_input_ex_protocol,
.drv_name = "efi_simple_text_input_ex",
- },
- {
.guid = &efi_guid_text_input_protocol,
.drv_name = "efi_simple_text_input",
- },
- {
.guid = &efi_guid_text_output_protocol,
.drv_name = "efi_simple_text_output",
- },
- {
.guid = &efi_guid_device_path,
.drv_name = "efi_device_path",
- },
- {
.guid = &efi_guid_device_path_to_text_protocol,
.drv_name = "efi_device_path_to_text",
- },
- {
.guid = &efi_guid_device_path_utilities_protocol,
.drv_name = "efi_device_path_utils",
- },
+#if defined(CONFIG_LCD) || defined(CONFIG_DM_VIDEO)
- {
.guid = &efi_gop_guid,
.drv_name = "efi_gop",
- },
+#endif +#if defined(CONFIG_NET)
- {
.guid = &efi_net_guid,
.drv_name = "efi_net",
- },
- {
.guid = &efi_net_guid,
.drv_name = "efi_pxe",
- },
+#endif
- {
.guid = &efi_guid_unicode_collation_protocol,
.drv_name = "efi_unicode_collation",
- },
- {
.guid = &efi_block_io_guid,
.drv_name = "efi_disk",
- },
- {
.guid = &efi_simple_file_system_protocol_guid,
.drv_name = "efi_simple_file_system",
- },
- {
.guid = &efi_guid_driver_binding_protocol,
.drv_name = "efi_driver_binding",
- },
+};
+static const char *get_protocol_drv_name(const efi_guid_t *guid) +{
- int i;
- for (i = 0; i < ARRAY_SIZE(protocol_list); i++)
if (!guidcmp(protocol_list[i].guid, guid))
return protocol_list[i].drv_name;
- return "efi_protocol";
+}
/**
- efi_add_protocol() - install new protocol on a handle
- @handle: handle on which the protocol shall be installed
@@ -985,28 +1149,36 @@ static efi_status_t efi_delete_open_info(
- Return: status code
*/ efi_status_t efi_add_protocol(const efi_handle_t handle,
const efi_guid_t *protocol,
const efi_guid_t *protocol_guid, void *protocol_interface)
{
- struct efi_object *efiobj;
- struct udevice *dev, *protocol; struct efi_handler *handler; efi_status_t ret;
- efiobj = efi_search_obj(handle);
- if (!efiobj)
- if (!efi_is_valid(handle)) return EFI_INVALID_PARAMETER;
- ret = efi_search_protocol(handle, protocol, NULL);
- dev = handle;
- ret = efi_search_protocol(handle, protocol_guid, NULL); if (ret != EFI_NOT_FOUND) return EFI_INVALID_PARAMETER;
- handler = calloc(1, sizeof(struct efi_handler));
- if (!handler)
- ret = device_bind_driver(dev, get_protocol_drv_name(protocol_guid),
"(PROTO)", &protocol);
- if (ret) return EFI_OUT_OF_RESOURCES;
- handler->guid = protocol;
- handler = protocol->uclass_platdata;
- handler->guid = protocol_guid; handler->protocol_interface = protocol_interface; INIT_LIST_HEAD(&handler->open_infos);
- list_add_tail(&handler->link, &efiobj->protocols);
- if (!guidcmp(&efi_guid_device_path, protocol))
- device_probe(protocol);
- if (!guidcmp(&efi_guid_device_path, protocol_guid)) EFI_PRINT("installed device path '%pD'\n", protocol_interface);
- return EFI_SUCCESS;
}
@@ -1042,7 +1214,7 @@ static efi_status_t EFIAPI efi_install_protocol_interface(
/* Create new handle if requested. */ if (!*handle) {
r = efi_create_handle(handle);
if (r != EFI_SUCCESS) goto out; debug("%sEFI: new handle %p\n", indent_string(nesting_level),r = efi_create_handle(handle, "(NO NAME)");
@@ -1073,13 +1245,20 @@ static efi_status_t efi_get_drivers(efi_handle_t handle, efi_uintn_t *number_of_drivers, efi_handle_t **driver_handle_buffer) {
struct udevice *dev, *child; struct efi_handler *handler; struct efi_open_protocol_info_item *item; efi_uintn_t count = 0, i; bool duplicate;
dev = handle;
/* Count all driver associations */
- list_for_each_entry(handler, &handle->protocols, link) {
- list_for_each_entry(child, &dev->child_head, sibling_node) {
if (child->driver->id != UCLASS_EFI_PROTOCOL)
continue;
if (protocol && guidcmp(handler->guid, protocol)) continue; list_for_each_entry(item, &handler->open_infos, link) {handler = child->uclass_platdata;
@@ -1097,7 +1276,11 @@ static efi_status_t efi_get_drivers(efi_handle_t handle, if (!*driver_handle_buffer) return EFI_OUT_OF_RESOURCES; /* Collect unique driver handles */
- list_for_each_entry(handler, &handle->protocols, link) {
- list_for_each_entry(child, &dev->child_head, sibling_node) {
if (child->driver->id != UCLASS_EFI_PROTOCOL)
continue;
if (protocol && guidcmp(handler->guid, protocol)) continue; list_for_each_entry(item, &handler->open_infos, link) {handler = child->uclass_platdata;
@@ -1173,28 +1356,27 @@ static efi_status_t efi_disconnect_all_drivers
- Return: status code
*/ -static efi_status_t efi_uninstall_protocol
(efi_handle_t handle, const efi_guid_t *protocol,
void *protocol_interface)
+static efi_status_t efi_uninstall_protocol(efi_handle_t handle,
const efi_guid_t *protocol_guid,
void *protocol_interface)
{
- struct efi_object *efiobj;
- struct udevice *protocol; struct efi_handler *handler; struct efi_open_protocol_info_item *item; struct efi_open_protocol_info_item *pos; efi_status_t r;
- /* Check handle */
- efiobj = efi_search_obj(handle);
- if (!efiobj) {
r = EFI_INVALID_PARAMETER;
goto out;
- }
- if (!efi_is_valid(handle))
return EFI_INVALID_PARAMETER;
- /* Find the protocol on the handle */
- r = efi_search_protocol(handle, protocol, &handler);
- r = efi_search_protocol(handle, protocol_guid, &protocol); if (r != EFI_SUCCESS) goto out;
- handler = protocol->uclass_platdata;
- /* Disconnect controllers */
- efi_disconnect_all_drivers(efiobj, protocol, NULL);
- efi_disconnect_all_drivers(handle, protocol_guid, NULL); if (!list_empty(&handler->open_infos)) { r = EFI_ACCESS_DENIED; goto out;
@@ -1211,7 +1393,7 @@ static efi_status_t efi_uninstall_protocol r = EFI_ACCESS_DENIED; goto out; }
- r = efi_remove_protocol(handle, protocol, protocol_interface);
- r = efi_remove_protocol(handle, protocol_guid, protocol_interface);
out: return r; } @@ -1242,10 +1424,9 @@ static efi_status_t EFIAPI efi_uninstall_protocol_interface goto out;
/* If the last protocol has been removed, delete the handle. */
- if (list_empty(&handle->protocols)) {
list_del(&handle->link);
free(handle);
- }
- if (device_find_first_child_by_uclass(handle, UCLASS_EFI_PROTOCOL,
NULL))
efi_remove_handle(handle);
out: return EFI_EXIT(ret); } @@ -1352,7 +1533,7 @@ static efi_status_t efi_locate_handle(
/* Count how much space we need */ list_for_each_entry(efiobj, &efi_obj_list, link) {
if (!efi_search(search_type, protocol, search_key, efiobj))
}if (!efi_search(search_type, protocol, search_key, efiobj->dev)) size += sizeof(void *);
@@ -1367,8 +1548,8 @@ static efi_status_t efi_locate_handle(
/* Then fill the array */ list_for_each_entry(efiobj, &efi_obj_list, link) {
if (!efi_search(search_type, protocol, search_key, efiobj))
*buffer++ = efiobj;
if (!efi_search(search_type, protocol, search_key, efiobj->dev))
*buffer++ = efiobj->dev;
}
return EFI_SUCCESS;
@@ -2012,25 +2193,27 @@ static efi_status_t EFIAPI efi_set_watchdog_timer(unsigned long timeout,
- Return: status code
*/ static efi_status_t EFIAPI efi_close_protocol(efi_handle_t handle,
const efi_guid_t *protocol,
const efi_guid_t *protocol_guid, efi_handle_t agent_handle, efi_handle_t controller_handle)
{
- struct udevice *protocol; struct efi_handler *handler; struct efi_open_protocol_info_item *item; struct efi_open_protocol_info_item *pos; efi_status_t r;
- EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, agent_handle,
EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol_guid, agent_handle, controller_handle);
if (!agent_handle) { r = EFI_INVALID_PARAMETER; goto out; }
- r = efi_search_protocol(handle, protocol, &handler);
r = efi_search_protocol(handle, protocol_guid, &protocol); if (r != EFI_SUCCESS) goto out;
handler = protocol->uclass_platdata;
r = EFI_NOT_FOUND; list_for_each_entry_safe(item, pos, &handler->open_infos, link) {
@@ -2061,17 +2244,18 @@ out:
- Return: status code
*/ static efi_status_t EFIAPI efi_open_protocol_information(
efi_handle_t handle, const efi_guid_t *protocol,
efi_handle_t handle, const efi_guid_t *protocol_guid, struct efi_open_protocol_info_entry **entry_buffer, efi_uintn_t *entry_count)
{ unsigned long buffer_size; unsigned long count;
- struct udevice *protocol; struct efi_handler *handler; struct efi_open_protocol_info_item *item; efi_status_t r;
- EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, entry_buffer,
EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol_guid, entry_buffer, entry_count);
/* Check parameters */
@@ -2079,9 +2263,10 @@ static efi_status_t EFIAPI efi_open_protocol_information( r = EFI_INVALID_PARAMETER; goto out; }
- r = efi_search_protocol(handle, protocol, &handler);
r = efi_search_protocol(handle, protocol_guid, &protocol); if (r != EFI_SUCCESS) goto out;
handler = protocol->uclass_platdata;
/* Count entries */ count = 0;
@@ -2127,9 +2312,8 @@ static efi_status_t EFIAPI efi_protocols_per_handle( efi_handle_t handle, efi_guid_t ***protocol_buffer, efi_uintn_t *protocol_buffer_count) {
- struct udevice *dev, *child; unsigned long buffer_size;
struct efi_object *efiobj;
struct list_head *protocol_handle; efi_status_t r;
EFI_ENTRY("%p, %p, %p", handle, protocol_buffer,
@@ -2141,12 +2325,15 @@ static efi_status_t EFIAPI efi_protocols_per_handle( *protocol_buffer = NULL; *protocol_buffer_count = 0;
- efiobj = efi_search_obj(handle);
- if (!efiobj)
return EFI_EXIT(EFI_INVALID_PARAMETER);
if (!efi_is_valid(handle))
return EFI_INVALID_PARAMETER;
dev = handle;
/* Count protocols */
- list_for_each(protocol_handle, &efiobj->protocols) {
- list_for_each_entry(child, &dev->child_head, sibling_node) {
if (child->driver->id != UCLASS_EFI_PROTOCOL)
continue;
- ++*protocol_buffer_count; }
@@ -2159,12 +2346,15 @@ static efi_status_t EFIAPI efi_protocols_per_handle( (void **)protocol_buffer); if (r != EFI_SUCCESS) return EFI_EXIT(r);
list_for_each(protocol_handle, &efiobj->protocols) {
struct efi_handler *protocol;
protocol = list_entry(protocol_handle,
struct efi_handler, link);
(*protocol_buffer)[j] = (void *)protocol->guid;
list_for_each_entry(child, &dev->child_head, sibling_node) {
struct efi_handler *handler;
if (child->driver->id != UCLASS_EFI_PROTOCOL)
continue;
handler = child->uclass_platdata;
} }(*protocol_buffer)[j] = (void *)handler->guid; ++j;
@@ -2233,26 +2423,27 @@ out:
- Return: status code
*/ -static efi_status_t EFIAPI efi_locate_protocol(const efi_guid_t *protocol, +static efi_status_t EFIAPI efi_locate_protocol(const efi_guid_t *protocol_guid, void *registration, void **protocol_interface) {
- struct list_head *lhandle;
- struct efi_object *efiobj; efi_status_t ret;
- EFI_ENTRY("%pUl, %p, %p", protocol, registration, protocol_interface);
- EFI_ENTRY("%pUl, %p, %p", protocol_guid, registration,
protocol_interface);
- if (!protocol || !protocol_interface)
- if (!protocol_guid || !protocol_interface) return EFI_EXIT(EFI_INVALID_PARAMETER);
- list_for_each(lhandle, &efi_obj_list) {
struct efi_object *efiobj;
- list_for_each_entry(efiobj, &efi_obj_list, link) { struct efi_handler *handler;
struct udevice *protocol;
efiobj = list_entry(lhandle, struct efi_object, link);
ret = efi_search_protocol(efiobj, protocol, &handler);
ret = efi_search_protocol(efiobj->dev, protocol_guid,
if (ret == EFI_SUCCESS) {&protocol);
}handler = protocol->uclass_platdata; *protocol_interface = handler->protocol_interface; return EFI_EXIT(EFI_SUCCESS);
@@ -2277,12 +2468,13 @@ static efi_status_t EFIAPI efi_locate_protocol(const efi_guid_t *protocol,
- Return: status code
*/ static efi_status_t EFIAPI efi_locate_device_path(
const efi_guid_t *protocol,
const efi_guid_t *protocol_guid, struct efi_device_path **device_path, efi_handle_t *device)
{ struct efi_device_path *dp; size_t i;
- struct udevice *protocol; struct efi_handler *handler; efi_handle_t *handles; size_t len, len_dp;
@@ -2291,9 +2483,9 @@ static efi_status_t EFIAPI efi_locate_device_path( u8 *remainder; efi_status_t ret;
- EFI_ENTRY("%pUl, %p, %p", protocol, device_path, device);
- EFI_ENTRY("%pUl, %p, %p", protocol_guid, device_path, device);
- if (!protocol || !device_path || !*device_path || !device) {
- if (!protocol_guid || !device_path || !*device_path || !device) { ret = EFI_INVALID_PARAMETER; goto out; }
@@ -2302,17 +2494,19 @@ static efi_status_t EFIAPI efi_locate_device_path( len = efi_dp_instance_size(*device_path);
/* Get all handles implementing the protocol */
- ret = EFI_CALL(efi_locate_handle_buffer(BY_PROTOCOL, protocol, NULL,
&no_handles, &handles));
ret = EFI_CALL(efi_locate_handle_buffer(BY_PROTOCOL, protocol_guid,
NULL, &no_handles, &handles));
if (ret != EFI_SUCCESS) goto out;
for (i = 0; i < no_handles; ++i) { /* Find the device path protocol */ ret = efi_search_protocol(handles[i], &efi_guid_device_path,
&handler);
if (ret != EFI_SUCCESS) continue;&protocol);
dp = (struct efi_device_path *)handler->protocol_interface; len_dp = efi_dp_instance_size(dp); /*handler = protocol->uclass_platdata;
@@ -2442,10 +2636,11 @@ static efi_status_t EFIAPI efi_uninstall_multiple_protocol_interfaces( efi_va_end(argptr); if (r == EFI_SUCCESS) { /* If the last protocol has been removed, delete the handle. */
if (list_empty(&handle->protocols)) {
list_del(&handle->link);
free(handle);
}
if (device_find_first_child_by_uclass(handle,
UCLASS_EFI_PROTOCOL,
NULL))
efi_remove_handle(handle);
- return EFI_EXIT(r); }
@@ -2635,18 +2830,19 @@ out:
- Return: status code
*/ static efi_status_t EFIAPI efi_open_protocol
(efi_handle_t handle, const efi_guid_t *protocol,
(efi_handle_t handle, const efi_guid_t *protocol_guid, void **protocol_interface, efi_handle_t agent_handle, efi_handle_t controller_handle, uint32_t attributes)
{
- struct udevice *protocol; struct efi_handler *handler; efi_status_t r = EFI_INVALID_PARAMETER;
- EFI_ENTRY("%p, %pUl, %p, %p, %p, 0x%x", handle, protocol,
- EFI_ENTRY("%p, %pUl, %p, %p, %p, 0x%x", handle, protocol_guid, protocol_interface, agent_handle, controller_handle, attributes);
- if (!handle || !protocol ||
- if (!handle || !protocol_guid || (!protocol_interface && attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) { goto out;
@@ -2663,23 +2859,26 @@ static efi_status_t EFIAPI efi_open_protocol /* fall-through */ case EFI_OPEN_PROTOCOL_BY_DRIVER: case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE:
/* Check that the controller handle is valid */
if (!efi_search_obj(controller_handle))
if (!efi_is_valid(controller_handle)) {
r = EFI_INVALID_PARAMETER; goto out;
/* fall-through */ case EFI_OPEN_PROTOCOL_EXCLUSIVE:}
/* Check that the agent handle is valid */
if (!efi_search_obj(agent_handle))
if (!efi_is_valid(agent_handle)) {
r = EFI_INVALID_PARAMETER; goto out;
break; default: goto out; }}
- r = efi_search_protocol(handle, protocol, &handler);
r = efi_search_protocol(handle, protocol_guid, &protocol); if (r != EFI_SUCCESS) goto out;
handler = protocol->uclass_platdata; r = efi_protocol_open(handler, protocol_interface, agent_handle, controller_handle, attributes);
out: @@ -2839,18 +3038,16 @@ static efi_status_t EFIAPI efi_connect_controller( struct efi_device_path *remain_device_path, bool recursive) {
- struct udevice *dev, *child; efi_status_t r; efi_status_t ret = EFI_NOT_FOUND;
struct efi_object *efiobj;
EFI_ENTRY("%p, %p, %p, %d", controller_handle, driver_image_handle, remain_device_path, recursive);
efiobj = efi_search_obj(controller_handle);
if (!efiobj) {
ret = EFI_INVALID_PARAMETER;
goto out;
}
if (!efi_is_valid(controller_handle))
return EFI_INVALID_PARAMETER;
dev = controller_handle;
r = efi_connect_single_controller(controller_handle, driver_image_handle,
@@ -2861,7 +3058,11 @@ static efi_status_t EFIAPI efi_connect_controller( struct efi_handler *handler; struct efi_open_protocol_info_item *item;
list_for_each_entry(handler, &efiobj->protocols, link) {
list_for_each_entry(child, &dev->child_head, sibling_node) {
if (child->driver->id != UCLASS_EFI_PROTOCOL)
continue;
handler = child->uclass_platdata; list_for_each_entry(item, &handler->open_infos, link) { if (item->info.attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
@@ -2880,7 +3081,7 @@ static efi_status_t EFIAPI efi_connect_controller( if (ret != EFI_SUCCESS && remain_device_path && remain_device_path->type == DEVICE_PATH_TYPE_END) ret = EFI_SUCCESS; -out:
- return EFI_EXIT(ret);
}
@@ -2945,18 +3146,23 @@ out:
- Return: status code
*/ static efi_status_t efi_get_child_controllers(
struct efi_object *efiobj,
struct udevice *dev, efi_handle_t driver_handle, efi_uintn_t *number_of_children, efi_handle_t **child_handle_buffer)
{
struct udevice *child; struct efi_handler *handler; struct efi_open_protocol_info_item *item; efi_uintn_t count = 0, i; bool duplicate;
/* Count all child controller associations */
- list_for_each_entry(handler, &efiobj->protocols, link) {
- list_for_each_entry(child, &dev->child_head, sibling_node) {
if (child->driver->id != UCLASS_EFI_PROTOCOL)
continue;
list_for_each_entry(item, &handler->open_infos, link) { if (item->info.agent_handle == driver_handle && item->info.attributes &handler = child->uclass_platdata;
@@ -2973,7 +3179,11 @@ static efi_status_t efi_get_child_controllers( if (!*child_handle_buffer) return EFI_OUT_OF_RESOURCES; /* Copy unique child handles */
- list_for_each_entry(handler, &efiobj->protocols, link) {
- list_for_each_entry(child, &dev->child_head, sibling_node) {
if (child->driver->id != UCLASS_EFI_PROTOCOL)
continue;
list_for_each_entry(item, &handler->open_infos, link) { if (item->info.agent_handle == driver_handle && item->info.attributes &handler = child->uclass_platdata;
@@ -3015,30 +3225,23 @@ static efi_status_t EFIAPI efi_disconnect_controller( efi_handle_t driver_image_handle, efi_handle_t child_handle) {
- struct udevice *dev; struct efi_driver_binding_protocol *binding_protocol; efi_handle_t *child_handle_buffer = NULL; size_t number_of_children = 0; efi_status_t r; size_t stop_count = 0;
struct efi_object *efiobj;
EFI_ENTRY("%p, %p, %p", controller_handle, driver_image_handle, child_handle);
efiobj = efi_search_obj(controller_handle);
if (!efiobj) {
r = EFI_INVALID_PARAMETER;
goto out;
}
if (child_handle && !efi_search_obj(child_handle)) {
r = EFI_INVALID_PARAMETER;
goto out;
}
if (!efi_is_valid(controller_handle))
return EFI_INVALID_PARAMETER;
dev = controller_handle;
/* If no driver handle is supplied, disconnect all drivers */ if (!driver_image_handle) {
r = efi_disconnect_all_drivers(efiobj, NULL, child_handle);
goto out; }r = efi_disconnect_all_drivers(dev, NULL, child_handle);
@@ -3047,7 +3250,7 @@ static efi_status_t EFIAPI efi_disconnect_controller( number_of_children = 1; child_handle_buffer = &child_handle; } else {
efi_get_child_controllers(efiobj,
efi_get_child_controllers(dev, driver_image_handle, &number_of_children, &child_handle_buffer);
@@ -3186,3 +3389,30 @@ efi_status_t efi_initialize_system_table(void)
return ret; }
+/*
- UEFI object -- any device with no corresponding u-boot device
- */
+U_BOOT_DRIVER(efi_dumb_obj) = {
- .name = "efi_dumb_object",
- .id = UCLASS_EFI_OBJECT,
+};
+UCLASS_DRIVER(efi_obj) = {
- .name = "efi_object",
- .id = UCLASS_EFI_OBJECT,
+};
+/*
- UEFI protocol
- */
+U_BOOT_DRIVER(efi_protocol) = {
- .name = "efi_protocol",
- .id = UCLASS_EFI_PROTOCOL,
+};
+UCLASS_DRIVER(efi_protocol) = {
- .name = "efi_protocol",
- .id = UCLASS_EFI_PROTOCOL,
- .per_device_platdata_auto_alloc_size = sizeof(struct efi_handler),
+};

Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- include/efi_loader.h | 2 +- lib/efi_loader/efi_boottime.c | 61 +++++++++++++++++++---------------- 2 files changed, 35 insertions(+), 28 deletions(-)
diff --git a/include/efi_loader.h b/include/efi_loader.h index 4d5e22564a72..5882cd7dd3b0 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -367,7 +367,7 @@ efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table /* Sets up a loaded image */ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, struct efi_device_path *file_path, - struct efi_loaded_image_obj **handle_ptr, + efi_handle_t *handle_ptr, struct efi_loaded_image **info_ptr); efi_status_t efi_load_image_from_path(struct efi_device_path *file_path, void **buffer); diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index d23e4fbbdf23..624156d4578b 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1690,29 +1690,29 @@ static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid, */ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, struct efi_device_path *file_path, - struct efi_loaded_image_obj **handle_ptr, + efi_handle_t *handle_ptr, struct efi_loaded_image **info_ptr) { efi_status_t ret; struct efi_loaded_image *info; - struct efi_loaded_image_obj *obj; + struct udevice *dev;
info = calloc(1, sizeof(*info)); if (!info) return EFI_OUT_OF_RESOURCES; - obj = calloc(1, sizeof(*obj)); - if (!obj) { + + ret = device_bind_driver(dm_root(), "efi_loaded_image", "(IMG)", &dev); + if (ret) { free(info); return EFI_OUT_OF_RESOURCES; }
- /* Add internal object to object list */ - efi_add_handle(&obj->header); + efi_add_handle(dev);
if (info_ptr) *info_ptr = info; if (handle_ptr) - *handle_ptr = obj; + *handle_ptr = dev;
info->revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION; info->file_path = file_path; @@ -1724,7 +1724,7 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, * When asking for the device path interface, return * bootefi_device_path */ - ret = efi_add_protocol(&obj->header, + ret = efi_add_protocol(dev, &efi_guid_device_path, device_path); if (ret != EFI_SUCCESS) goto failure; @@ -1734,24 +1734,24 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, * When asking for the loaded_image interface, just * return handle which points to loaded_image_info */ - ret = efi_add_protocol(&obj->header, + ret = efi_add_protocol(dev, &efi_guid_loaded_image, info); if (ret != EFI_SUCCESS) goto failure;
- ret = efi_add_protocol(&obj->header, + ret = efi_add_protocol(dev, &efi_guid_hii_string_protocol, (void *)&efi_hii_string); if (ret != EFI_SUCCESS) goto failure;
- ret = efi_add_protocol(&obj->header, + ret = efi_add_protocol(dev, &efi_guid_hii_database_protocol, (void *)&efi_hii_database); if (ret != EFI_SUCCESS) goto failure;
- ret = efi_add_protocol(&obj->header, + ret = efi_add_protocol(dev, &efi_guid_hii_config_routing_protocol, (void *)&efi_hii_config_routing); if (ret != EFI_SUCCESS) @@ -1835,9 +1835,8 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy, efi_uintn_t source_size, efi_handle_t *image_handle) { + struct efi_loaded_image_obj *obj; struct efi_loaded_image *info = NULL; - struct efi_loaded_image_obj **image_obj = - (struct efi_loaded_image_obj **)image_handle; efi_status_t ret;
EFI_ENTRY("%d, %p, %pD, %p, %zd, %p", boot_policy, parent_image, @@ -1864,24 +1863,29 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy, * file parts: */ efi_dp_split_file_path(file_path, &dp, &fp); - ret = efi_setup_loaded_image(dp, fp, image_obj, &info); + ret = efi_setup_loaded_image(dp, fp, image_handle, &info); if (ret != EFI_SUCCESS) goto failure; } else { /* In this case, file_path is the "device" path, i.e. * something like a HARDWARE_DEVICE:MEMORY_MAPPED */ - ret = efi_setup_loaded_image(file_path, NULL, image_obj, &info); + ret = efi_setup_loaded_image(file_path, NULL, image_handle, + &info); if (ret != EFI_SUCCESS) goto error; } - (*image_obj)->entry = efi_load_pe(*image_obj, source_buffer, info); - if (!(*image_obj)->entry) { + + obj = (*image_handle)->platdata; + ret = efi_load_pe(obj, source_buffer, info); + if (ret != EFI_SUCCESS) { ret = EFI_UNSUPPORTED; goto failure; } + info->system_table = &systab; info->parent_handle = parent_image; + return EFI_EXIT(EFI_SUCCESS); failure: efi_delete_handle(*image_handle); @@ -1908,8 +1912,8 @@ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, unsigned long *exit_data_size, s16 **exit_data) { - struct efi_loaded_image_obj *image_obj = - (struct efi_loaded_image_obj *)image_handle; + struct udevice *dev = image_handle; + struct efi_loaded_image_obj *image_obj = dev->platdata; efi_status_t ret;
EFI_ENTRY("%p, %p, %p", image_handle, exit_data_size, exit_data); @@ -1975,12 +1979,12 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, unsigned long exit_data_size, int16_t *exit_data) { + struct udevice *dev = image_handle; + struct efi_loaded_image_obj *image_obj = dev->platdata; /* * TODO: We should call the unload procedure of the loaded * image protocol. */ - struct efi_loaded_image_obj *image_obj = - (struct efi_loaded_image_obj *)image_handle;
EFI_ENTRY("%p, %ld, %ld, %p", image_handle, exit_status, exit_data_size, exit_data); @@ -2013,12 +2017,9 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, */ static efi_status_t EFIAPI efi_unload_image(efi_handle_t image_handle) { - struct efi_object *efiobj; - EFI_ENTRY("%p", image_handle); - efiobj = efi_search_obj(image_handle); - if (efiobj) - list_del(&efiobj->link); + + efi_remove_handle(image_handle);
return EFI_EXIT(EFI_SUCCESS); } @@ -3398,6 +3399,12 @@ U_BOOT_DRIVER(efi_dumb_obj) = { .id = UCLASS_EFI_OBJECT, };
+U_BOOT_DRIVER(efi_image_obj) = { + .name = "efi_loaded_image", + .id = UCLASS_EFI_OBJECT, + .platdata_auto_alloc_size = sizeof(struct efi_loaded_image_obj), +}; + UCLASS_DRIVER(efi_obj) = { .name = "efi_object", .id = UCLASS_EFI_OBJECT,

On 2/8/19 9:15 AM, AKASHI Takahiro wrote:
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
include/efi_loader.h | 2 +- lib/efi_loader/efi_boottime.c | 61 +++++++++++++++++++---------------- 2 files changed, 35 insertions(+), 28 deletions(-)
diff --git a/include/efi_loader.h b/include/efi_loader.h index 4d5e22564a72..5882cd7dd3b0 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -367,7 +367,7 @@ efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table /* Sets up a loaded image */ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, struct efi_device_path *file_path,
struct efi_loaded_image_obj **handle_ptr,
efi_handle_t *handle_ptr, struct efi_loaded_image **info_ptr);
efi_status_t efi_load_image_from_path(struct efi_device_path *file_path, void **buffer); diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index d23e4fbbdf23..624156d4578b 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1690,29 +1690,29 @@ static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid, */ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, struct efi_device_path *file_path,
struct efi_loaded_image_obj **handle_ptr,
efi_handle_t *handle_ptr, struct efi_loaded_image **info_ptr)
{ efi_status_t ret; struct efi_loaded_image *info;
- struct efi_loaded_image_obj *obj;
struct udevice *dev;
info = calloc(1, sizeof(*info)); if (!info) return EFI_OUT_OF_RESOURCES;
- obj = calloc(1, sizeof(*obj));
- if (!obj) {
- ret = device_bind_driver(dm_root(), "efi_loaded_image", "(IMG)", &dev);
A loaded image is not a device. There is nothing in the EFI world relating the loaded image directly to the root of the device tree.
We should not create a meaningless link here.
Best regards
Heinrich
- if (ret) { free(info); return EFI_OUT_OF_RESOURCES; }
- /* Add internal object to object list */
- efi_add_handle(&obj->header);
efi_add_handle(dev);
if (info_ptr) *info_ptr = info; if (handle_ptr)
*handle_ptr = obj;
*handle_ptr = dev;
info->revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION; info->file_path = file_path;
@@ -1724,7 +1724,7 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, * When asking for the device path interface, return * bootefi_device_path */
ret = efi_add_protocol(&obj->header,
if (ret != EFI_SUCCESS) goto failure;ret = efi_add_protocol(dev, &efi_guid_device_path, device_path);
@@ -1734,24 +1734,24 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, * When asking for the loaded_image interface, just * return handle which points to loaded_image_info */
- ret = efi_add_protocol(&obj->header,
- ret = efi_add_protocol(dev, &efi_guid_loaded_image, info); if (ret != EFI_SUCCESS) goto failure;
- ret = efi_add_protocol(&obj->header,
- ret = efi_add_protocol(dev, &efi_guid_hii_string_protocol, (void *)&efi_hii_string); if (ret != EFI_SUCCESS) goto failure;
- ret = efi_add_protocol(&obj->header,
- ret = efi_add_protocol(dev, &efi_guid_hii_database_protocol, (void *)&efi_hii_database); if (ret != EFI_SUCCESS) goto failure;
- ret = efi_add_protocol(&obj->header,
- ret = efi_add_protocol(dev, &efi_guid_hii_config_routing_protocol, (void *)&efi_hii_config_routing); if (ret != EFI_SUCCESS)
@@ -1835,9 +1835,8 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy, efi_uintn_t source_size, efi_handle_t *image_handle) {
- struct efi_loaded_image_obj *obj; struct efi_loaded_image *info = NULL;
struct efi_loaded_image_obj **image_obj =
(struct efi_loaded_image_obj **)image_handle;
efi_status_t ret;
EFI_ENTRY("%d, %p, %pD, %p, %zd, %p", boot_policy, parent_image,
@@ -1864,24 +1863,29 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy, * file parts: */ efi_dp_split_file_path(file_path, &dp, &fp);
ret = efi_setup_loaded_image(dp, fp, image_obj, &info);
if (ret != EFI_SUCCESS) goto failure; } else { /* In this case, file_path is the "device" path, i.e.ret = efi_setup_loaded_image(dp, fp, image_handle, &info);
*/
- something like a HARDWARE_DEVICE:MEMORY_MAPPED
ret = efi_setup_loaded_image(file_path, NULL, image_obj, &info);
ret = efi_setup_loaded_image(file_path, NULL, image_handle,
if (ret != EFI_SUCCESS) goto error; }&info);
- (*image_obj)->entry = efi_load_pe(*image_obj, source_buffer, info);
- if (!(*image_obj)->entry) {
- obj = (*image_handle)->platdata;
- ret = efi_load_pe(obj, source_buffer, info);
- if (ret != EFI_SUCCESS) { ret = EFI_UNSUPPORTED; goto failure; }
- info->system_table = &systab; info->parent_handle = parent_image;
- return EFI_EXIT(EFI_SUCCESS);
failure: efi_delete_handle(*image_handle); @@ -1908,8 +1912,8 @@ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, unsigned long *exit_data_size, s16 **exit_data) {
- struct efi_loaded_image_obj *image_obj =
(struct efi_loaded_image_obj *)image_handle;
struct udevice *dev = image_handle;
struct efi_loaded_image_obj *image_obj = dev->platdata; efi_status_t ret;
EFI_ENTRY("%p, %p, %p", image_handle, exit_data_size, exit_data);
@@ -1975,12 +1979,12 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, unsigned long exit_data_size, int16_t *exit_data) {
- struct udevice *dev = image_handle;
- struct efi_loaded_image_obj *image_obj = dev->platdata; /*
*/
- TODO: We should call the unload procedure of the loaded
image protocol.
struct efi_loaded_image_obj *image_obj =
(struct efi_loaded_image_obj *)image_handle;
EFI_ENTRY("%p, %ld, %ld, %p", image_handle, exit_status, exit_data_size, exit_data);
@@ -2013,12 +2017,9 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, */ static efi_status_t EFIAPI efi_unload_image(efi_handle_t image_handle) {
- struct efi_object *efiobj;
- EFI_ENTRY("%p", image_handle);
- efiobj = efi_search_obj(image_handle);
- if (efiobj)
list_del(&efiobj->link);
efi_remove_handle(image_handle);
return EFI_EXIT(EFI_SUCCESS);
} @@ -3398,6 +3399,12 @@ U_BOOT_DRIVER(efi_dumb_obj) = { .id = UCLASS_EFI_OBJECT, };
+U_BOOT_DRIVER(efi_image_obj) = {
- .name = "efi_loaded_image",
- .id = UCLASS_EFI_OBJECT,
- .platdata_auto_alloc_size = sizeof(struct efi_loaded_image_obj),
+};
UCLASS_DRIVER(efi_obj) = { .name = "efi_object", .id = UCLASS_EFI_OBJECT,

Heinrich,
On Fri, Feb 08, 2019 at 06:53:00PM +0100, Heinrich Schuchardt wrote:
On 2/8/19 9:15 AM, AKASHI Takahiro wrote:
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
include/efi_loader.h | 2 +- lib/efi_loader/efi_boottime.c | 61 +++++++++++++++++++---------------- 2 files changed, 35 insertions(+), 28 deletions(-)
diff --git a/include/efi_loader.h b/include/efi_loader.h index 4d5e22564a72..5882cd7dd3b0 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -367,7 +367,7 @@ efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table /* Sets up a loaded image */ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, struct efi_device_path *file_path,
struct efi_loaded_image_obj **handle_ptr,
efi_handle_t *handle_ptr, struct efi_loaded_image **info_ptr);
efi_status_t efi_load_image_from_path(struct efi_device_path *file_path, void **buffer); diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index d23e4fbbdf23..624156d4578b 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1690,29 +1690,29 @@ static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid, */ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, struct efi_device_path *file_path,
struct efi_loaded_image_obj **handle_ptr,
efi_handle_t *handle_ptr, struct efi_loaded_image **info_ptr)
{ efi_status_t ret; struct efi_loaded_image *info;
- struct efi_loaded_image_obj *obj;
struct udevice *dev;
info = calloc(1, sizeof(*info)); if (!info) return EFI_OUT_OF_RESOURCES;
- obj = calloc(1, sizeof(*obj));
- if (!obj) {
- ret = device_bind_driver(dm_root(), "efi_loaded_image", "(IMG)", &dev);
A loaded image is not a device. There is nothing in the EFI world relating the loaded image directly to the root of the device tree.
Please notice that any loaded image is linked to "efi_root", not "root of the device tree."
Such a relationship is an analogy to the current implementation where *global* protocols are added to "efi_root" for now.
-Takahiro Akashi
We should not create a meaningless link here.
Best regards
Heinrich
- if (ret) { free(info); return EFI_OUT_OF_RESOURCES; }
- /* Add internal object to object list */
- efi_add_handle(&obj->header);
efi_add_handle(dev);
if (info_ptr) *info_ptr = info; if (handle_ptr)
*handle_ptr = obj;
*handle_ptr = dev;
info->revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION; info->file_path = file_path;
@@ -1724,7 +1724,7 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, * When asking for the device path interface, return * bootefi_device_path */
ret = efi_add_protocol(&obj->header,
if (ret != EFI_SUCCESS) goto failure;ret = efi_add_protocol(dev, &efi_guid_device_path, device_path);
@@ -1734,24 +1734,24 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, * When asking for the loaded_image interface, just * return handle which points to loaded_image_info */
- ret = efi_add_protocol(&obj->header,
- ret = efi_add_protocol(dev, &efi_guid_loaded_image, info); if (ret != EFI_SUCCESS) goto failure;
- ret = efi_add_protocol(&obj->header,
- ret = efi_add_protocol(dev, &efi_guid_hii_string_protocol, (void *)&efi_hii_string); if (ret != EFI_SUCCESS) goto failure;
- ret = efi_add_protocol(&obj->header,
- ret = efi_add_protocol(dev, &efi_guid_hii_database_protocol, (void *)&efi_hii_database); if (ret != EFI_SUCCESS) goto failure;
- ret = efi_add_protocol(&obj->header,
- ret = efi_add_protocol(dev, &efi_guid_hii_config_routing_protocol, (void *)&efi_hii_config_routing); if (ret != EFI_SUCCESS)
@@ -1835,9 +1835,8 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy, efi_uintn_t source_size, efi_handle_t *image_handle) {
- struct efi_loaded_image_obj *obj; struct efi_loaded_image *info = NULL;
struct efi_loaded_image_obj **image_obj =
(struct efi_loaded_image_obj **)image_handle;
efi_status_t ret;
EFI_ENTRY("%d, %p, %pD, %p, %zd, %p", boot_policy, parent_image,
@@ -1864,24 +1863,29 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy, * file parts: */ efi_dp_split_file_path(file_path, &dp, &fp);
ret = efi_setup_loaded_image(dp, fp, image_obj, &info);
if (ret != EFI_SUCCESS) goto failure; } else { /* In this case, file_path is the "device" path, i.e.ret = efi_setup_loaded_image(dp, fp, image_handle, &info);
*/
- something like a HARDWARE_DEVICE:MEMORY_MAPPED
ret = efi_setup_loaded_image(file_path, NULL, image_obj, &info);
ret = efi_setup_loaded_image(file_path, NULL, image_handle,
if (ret != EFI_SUCCESS) goto error; }&info);
- (*image_obj)->entry = efi_load_pe(*image_obj, source_buffer, info);
- if (!(*image_obj)->entry) {
- obj = (*image_handle)->platdata;
- ret = efi_load_pe(obj, source_buffer, info);
- if (ret != EFI_SUCCESS) { ret = EFI_UNSUPPORTED; goto failure; }
- info->system_table = &systab; info->parent_handle = parent_image;
- return EFI_EXIT(EFI_SUCCESS);
failure: efi_delete_handle(*image_handle); @@ -1908,8 +1912,8 @@ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, unsigned long *exit_data_size, s16 **exit_data) {
- struct efi_loaded_image_obj *image_obj =
(struct efi_loaded_image_obj *)image_handle;
struct udevice *dev = image_handle;
struct efi_loaded_image_obj *image_obj = dev->platdata; efi_status_t ret;
EFI_ENTRY("%p, %p, %p", image_handle, exit_data_size, exit_data);
@@ -1975,12 +1979,12 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, unsigned long exit_data_size, int16_t *exit_data) {
- struct udevice *dev = image_handle;
- struct efi_loaded_image_obj *image_obj = dev->platdata; /*
*/
- TODO: We should call the unload procedure of the loaded
image protocol.
struct efi_loaded_image_obj *image_obj =
(struct efi_loaded_image_obj *)image_handle;
EFI_ENTRY("%p, %ld, %ld, %p", image_handle, exit_status, exit_data_size, exit_data);
@@ -2013,12 +2017,9 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, */ static efi_status_t EFIAPI efi_unload_image(efi_handle_t image_handle) {
- struct efi_object *efiobj;
- EFI_ENTRY("%p", image_handle);
- efiobj = efi_search_obj(image_handle);
- if (efiobj)
list_del(&efiobj->link);
efi_remove_handle(image_handle);
return EFI_EXIT(EFI_SUCCESS);
} @@ -3398,6 +3399,12 @@ U_BOOT_DRIVER(efi_dumb_obj) = { .id = UCLASS_EFI_OBJECT, };
+U_BOOT_DRIVER(efi_image_obj) = {
- .name = "efi_loaded_image",
- .id = UCLASS_EFI_OBJECT,
- .platdata_auto_alloc_size = sizeof(struct efi_loaded_image_obj),
+};
UCLASS_DRIVER(efi_obj) = { .name = "efi_object", .id = UCLASS_EFI_OBJECT,

On 2/12/19 6:07 AM, AKASHI Takahiro wrote:
Heinrich,
On Fri, Feb 08, 2019 at 06:53:00PM +0100, Heinrich Schuchardt wrote:
On 2/8/19 9:15 AM, AKASHI Takahiro wrote:
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
include/efi_loader.h | 2 +- lib/efi_loader/efi_boottime.c | 61 +++++++++++++++++++---------------- 2 files changed, 35 insertions(+), 28 deletions(-)
diff --git a/include/efi_loader.h b/include/efi_loader.h index 4d5e22564a72..5882cd7dd3b0 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -367,7 +367,7 @@ efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table /* Sets up a loaded image */ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, struct efi_device_path *file_path,
struct efi_loaded_image_obj **handle_ptr,
efi_handle_t *handle_ptr, struct efi_loaded_image **info_ptr);
efi_status_t efi_load_image_from_path(struct efi_device_path *file_path, void **buffer); diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index d23e4fbbdf23..624156d4578b 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1690,29 +1690,29 @@ static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid, */ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, struct efi_device_path *file_path,
struct efi_loaded_image_obj **handle_ptr,
efi_handle_t *handle_ptr, struct efi_loaded_image **info_ptr)
{ efi_status_t ret; struct efi_loaded_image *info;
- struct efi_loaded_image_obj *obj;
struct udevice *dev;
info = calloc(1, sizeof(*info)); if (!info) return EFI_OUT_OF_RESOURCES;
- obj = calloc(1, sizeof(*obj));
- if (!obj) {
- ret = device_bind_driver(dm_root(), "efi_loaded_image", "(IMG)", &dev);
A loaded image is not a device. There is nothing in the EFI world relating the loaded image directly to the root of the device tree.
Please notice that any loaded image is linked to "efi_root", not "root of the device tree."
Such a relationship is an analogy to the current implementation where *global* protocols are added to "efi_root" for now.
Yes we are lacking the necessary handles to show that the USB keyboard in connected to a USB controller installed on a PCI bus.
But what has this to do with loaded images? When we call the U-Boot `load` command to load a kernel image we do not update the device model. So why should be do it for a kernel image loaded via LoadImage()?
A kernel image isn't a device. So let's keep it separate from the device mmodel.
Best regards
Heinrich
-Takahiro Akashi
We should not create a meaningless link here.
Best regards
Heinrich
- if (ret) { free(info); return EFI_OUT_OF_RESOURCES; }
- /* Add internal object to object list */
- efi_add_handle(&obj->header);
efi_add_handle(dev);
if (info_ptr) *info_ptr = info; if (handle_ptr)
*handle_ptr = obj;
*handle_ptr = dev;
info->revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION; info->file_path = file_path;
@@ -1724,7 +1724,7 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, * When asking for the device path interface, return * bootefi_device_path */
ret = efi_add_protocol(&obj->header,
if (ret != EFI_SUCCESS) goto failure;ret = efi_add_protocol(dev, &efi_guid_device_path, device_path);
@@ -1734,24 +1734,24 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, * When asking for the loaded_image interface, just * return handle which points to loaded_image_info */
- ret = efi_add_protocol(&obj->header,
- ret = efi_add_protocol(dev, &efi_guid_loaded_image, info); if (ret != EFI_SUCCESS) goto failure;
- ret = efi_add_protocol(&obj->header,
- ret = efi_add_protocol(dev, &efi_guid_hii_string_protocol, (void *)&efi_hii_string); if (ret != EFI_SUCCESS) goto failure;
- ret = efi_add_protocol(&obj->header,
- ret = efi_add_protocol(dev, &efi_guid_hii_database_protocol, (void *)&efi_hii_database); if (ret != EFI_SUCCESS) goto failure;
- ret = efi_add_protocol(&obj->header,
- ret = efi_add_protocol(dev, &efi_guid_hii_config_routing_protocol, (void *)&efi_hii_config_routing); if (ret != EFI_SUCCESS)
@@ -1835,9 +1835,8 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy, efi_uintn_t source_size, efi_handle_t *image_handle) {
- struct efi_loaded_image_obj *obj; struct efi_loaded_image *info = NULL;
struct efi_loaded_image_obj **image_obj =
(struct efi_loaded_image_obj **)image_handle;
efi_status_t ret;
EFI_ENTRY("%d, %p, %pD, %p, %zd, %p", boot_policy, parent_image,
@@ -1864,24 +1863,29 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy, * file parts: */ efi_dp_split_file_path(file_path, &dp, &fp);
ret = efi_setup_loaded_image(dp, fp, image_obj, &info);
if (ret != EFI_SUCCESS) goto failure; } else { /* In this case, file_path is the "device" path, i.e.ret = efi_setup_loaded_image(dp, fp, image_handle, &info);
*/
- something like a HARDWARE_DEVICE:MEMORY_MAPPED
ret = efi_setup_loaded_image(file_path, NULL, image_obj, &info);
ret = efi_setup_loaded_image(file_path, NULL, image_handle,
if (ret != EFI_SUCCESS) goto error; }&info);
- (*image_obj)->entry = efi_load_pe(*image_obj, source_buffer, info);
- if (!(*image_obj)->entry) {
- obj = (*image_handle)->platdata;
- ret = efi_load_pe(obj, source_buffer, info);
- if (ret != EFI_SUCCESS) { ret = EFI_UNSUPPORTED; goto failure; }
- info->system_table = &systab; info->parent_handle = parent_image;
- return EFI_EXIT(EFI_SUCCESS);
failure: efi_delete_handle(*image_handle); @@ -1908,8 +1912,8 @@ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, unsigned long *exit_data_size, s16 **exit_data) {
- struct efi_loaded_image_obj *image_obj =
(struct efi_loaded_image_obj *)image_handle;
struct udevice *dev = image_handle;
struct efi_loaded_image_obj *image_obj = dev->platdata; efi_status_t ret;
EFI_ENTRY("%p, %p, %p", image_handle, exit_data_size, exit_data);
@@ -1975,12 +1979,12 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, unsigned long exit_data_size, int16_t *exit_data) {
- struct udevice *dev = image_handle;
- struct efi_loaded_image_obj *image_obj = dev->platdata; /*
*/
- TODO: We should call the unload procedure of the loaded
image protocol.
struct efi_loaded_image_obj *image_obj =
(struct efi_loaded_image_obj *)image_handle;
EFI_ENTRY("%p, %ld, %ld, %p", image_handle, exit_status, exit_data_size, exit_data);
@@ -2013,12 +2017,9 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, */ static efi_status_t EFIAPI efi_unload_image(efi_handle_t image_handle) {
- struct efi_object *efiobj;
- EFI_ENTRY("%p", image_handle);
- efiobj = efi_search_obj(image_handle);
- if (efiobj)
list_del(&efiobj->link);
efi_remove_handle(image_handle);
return EFI_EXIT(EFI_SUCCESS);
} @@ -3398,6 +3399,12 @@ U_BOOT_DRIVER(efi_dumb_obj) = { .id = UCLASS_EFI_OBJECT, };
+U_BOOT_DRIVER(efi_image_obj) = {
- .name = "efi_loaded_image",
- .id = UCLASS_EFI_OBJECT,
- .platdata_auto_alloc_size = sizeof(struct efi_loaded_image_obj),
+};
UCLASS_DRIVER(efi_obj) = { .name = "efi_object", .id = UCLASS_EFI_OBJECT,

On Tue, Feb 12, 2019 at 07:47:06AM +0100, Heinrich Schuchardt wrote:
On 2/12/19 6:07 AM, AKASHI Takahiro wrote:
Heinrich,
On Fri, Feb 08, 2019 at 06:53:00PM +0100, Heinrich Schuchardt wrote:
On 2/8/19 9:15 AM, AKASHI Takahiro wrote:
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
include/efi_loader.h | 2 +- lib/efi_loader/efi_boottime.c | 61 +++++++++++++++++++---------------- 2 files changed, 35 insertions(+), 28 deletions(-)
diff --git a/include/efi_loader.h b/include/efi_loader.h index 4d5e22564a72..5882cd7dd3b0 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -367,7 +367,7 @@ efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table /* Sets up a loaded image */ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, struct efi_device_path *file_path,
struct efi_loaded_image_obj **handle_ptr,
efi_handle_t *handle_ptr, struct efi_loaded_image **info_ptr);
efi_status_t efi_load_image_from_path(struct efi_device_path *file_path, void **buffer); diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index d23e4fbbdf23..624156d4578b 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1690,29 +1690,29 @@ static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid, */ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, struct efi_device_path *file_path,
struct efi_loaded_image_obj **handle_ptr,
efi_handle_t *handle_ptr, struct efi_loaded_image **info_ptr)
{ efi_status_t ret; struct efi_loaded_image *info;
- struct efi_loaded_image_obj *obj;
struct udevice *dev;
info = calloc(1, sizeof(*info)); if (!info) return EFI_OUT_OF_RESOURCES;
- obj = calloc(1, sizeof(*obj));
- if (!obj) {
- ret = device_bind_driver(dm_root(), "efi_loaded_image", "(IMG)", &dev);
A loaded image is not a device. There is nothing in the EFI world relating the loaded image directly to the root of the device tree.
Please notice that any loaded image is linked to "efi_root", not "root of the device tree."
Such a relationship is an analogy to the current implementation where *global* protocols are added to "efi_root" for now.
Yes we are lacking the necessary handles to show that the USB keyboard in connected to a USB controller installed on a PCI bus.
But what has this to do with loaded images? When we call the U-Boot `load` command to load a kernel image we do not update the device model.
That's right.
So why should be do it for a kernel image loaded via LoadImage()?
The difference here is that multiple instances of loaded image, either application or driver, can co-exist at the same time in EFI world. So distinguishing those by handles may make some sense.
-Takahiro Akashi
A kernel image isn't a device. So let's keep it separate from the device mmodel.
Best regards
Heinrich
-Takahiro Akashi
We should not create a meaningless link here.
Best regards
Heinrich
- if (ret) { free(info); return EFI_OUT_OF_RESOURCES; }
- /* Add internal object to object list */
- efi_add_handle(&obj->header);
efi_add_handle(dev);
if (info_ptr) *info_ptr = info; if (handle_ptr)
*handle_ptr = obj;
*handle_ptr = dev;
info->revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION; info->file_path = file_path;
@@ -1724,7 +1724,7 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, * When asking for the device path interface, return * bootefi_device_path */
ret = efi_add_protocol(&obj->header,
if (ret != EFI_SUCCESS) goto failure;ret = efi_add_protocol(dev, &efi_guid_device_path, device_path);
@@ -1734,24 +1734,24 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, * When asking for the loaded_image interface, just * return handle which points to loaded_image_info */
- ret = efi_add_protocol(&obj->header,
- ret = efi_add_protocol(dev, &efi_guid_loaded_image, info); if (ret != EFI_SUCCESS) goto failure;
- ret = efi_add_protocol(&obj->header,
- ret = efi_add_protocol(dev, &efi_guid_hii_string_protocol, (void *)&efi_hii_string); if (ret != EFI_SUCCESS) goto failure;
- ret = efi_add_protocol(&obj->header,
- ret = efi_add_protocol(dev, &efi_guid_hii_database_protocol, (void *)&efi_hii_database); if (ret != EFI_SUCCESS) goto failure;
- ret = efi_add_protocol(&obj->header,
- ret = efi_add_protocol(dev, &efi_guid_hii_config_routing_protocol, (void *)&efi_hii_config_routing); if (ret != EFI_SUCCESS)
@@ -1835,9 +1835,8 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy, efi_uintn_t source_size, efi_handle_t *image_handle) {
- struct efi_loaded_image_obj *obj; struct efi_loaded_image *info = NULL;
struct efi_loaded_image_obj **image_obj =
(struct efi_loaded_image_obj **)image_handle;
efi_status_t ret;
EFI_ENTRY("%d, %p, %pD, %p, %zd, %p", boot_policy, parent_image,
@@ -1864,24 +1863,29 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy, * file parts: */ efi_dp_split_file_path(file_path, &dp, &fp);
ret = efi_setup_loaded_image(dp, fp, image_obj, &info);
if (ret != EFI_SUCCESS) goto failure; } else { /* In this case, file_path is the "device" path, i.e.ret = efi_setup_loaded_image(dp, fp, image_handle, &info);
*/
- something like a HARDWARE_DEVICE:MEMORY_MAPPED
ret = efi_setup_loaded_image(file_path, NULL, image_obj, &info);
ret = efi_setup_loaded_image(file_path, NULL, image_handle,
if (ret != EFI_SUCCESS) goto error; }&info);
- (*image_obj)->entry = efi_load_pe(*image_obj, source_buffer, info);
- if (!(*image_obj)->entry) {
- obj = (*image_handle)->platdata;
- ret = efi_load_pe(obj, source_buffer, info);
- if (ret != EFI_SUCCESS) { ret = EFI_UNSUPPORTED; goto failure; }
- info->system_table = &systab; info->parent_handle = parent_image;
- return EFI_EXIT(EFI_SUCCESS);
failure: efi_delete_handle(*image_handle); @@ -1908,8 +1912,8 @@ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, unsigned long *exit_data_size, s16 **exit_data) {
- struct efi_loaded_image_obj *image_obj =
(struct efi_loaded_image_obj *)image_handle;
struct udevice *dev = image_handle;
struct efi_loaded_image_obj *image_obj = dev->platdata; efi_status_t ret;
EFI_ENTRY("%p, %p, %p", image_handle, exit_data_size, exit_data);
@@ -1975,12 +1979,12 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, unsigned long exit_data_size, int16_t *exit_data) {
- struct udevice *dev = image_handle;
- struct efi_loaded_image_obj *image_obj = dev->platdata; /*
*/
- TODO: We should call the unload procedure of the loaded
image protocol.
struct efi_loaded_image_obj *image_obj =
(struct efi_loaded_image_obj *)image_handle;
EFI_ENTRY("%p, %ld, %ld, %p", image_handle, exit_status, exit_data_size, exit_data);
@@ -2013,12 +2017,9 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, */ static efi_status_t EFIAPI efi_unload_image(efi_handle_t image_handle) {
- struct efi_object *efiobj;
- EFI_ENTRY("%p", image_handle);
- efiobj = efi_search_obj(image_handle);
- if (efiobj)
list_del(&efiobj->link);
efi_remove_handle(image_handle);
return EFI_EXIT(EFI_SUCCESS);
} @@ -3398,6 +3399,12 @@ U_BOOT_DRIVER(efi_dumb_obj) = { .id = UCLASS_EFI_OBJECT, };
+U_BOOT_DRIVER(efi_image_obj) = {
- .name = "efi_loaded_image",
- .id = UCLASS_EFI_OBJECT,
- .platdata_auto_alloc_size = sizeof(struct efi_loaded_image_obj),
+};
UCLASS_DRIVER(efi_obj) = { .name = "efi_object", .id = UCLASS_EFI_OBJECT,

Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- cmd/bootefi.c | 61 ++++++++++++++----------------- include/efi_loader.h | 4 +- lib/efi_loader/efi_image_loader.c | 61 +++++++++++++++++++------------ 3 files changed, 67 insertions(+), 59 deletions(-)
diff --git a/cmd/bootefi.c b/cmd/bootefi.c index ebe149dffa1f..d2130d5ac323 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -249,12 +249,12 @@ static efi_status_t efi_install_fdt(ulong fdt_addr) static efi_status_t bootefi_run_prepare(const char *load_options_path, struct efi_device_path *device_path, struct efi_device_path *image_path, - struct efi_loaded_image_obj **image_objp, + efi_handle_t *handlep, struct efi_loaded_image **loaded_image_infop) { efi_status_t ret;
- ret = efi_setup_loaded_image(device_path, image_path, image_objp, + ret = efi_setup_loaded_image(device_path, image_path, handlep, loaded_image_infop); if (ret != EFI_SUCCESS) return ret; @@ -268,15 +268,15 @@ static efi_status_t bootefi_run_prepare(const char *load_options_path, /** * bootefi_run_finish() - finish up after running an EFI test * + * @handle: Handle to the loaded image object * @loaded_image_info: Pointer to a struct which holds the loaded image info - * @image_objj: Pointer to a struct which holds the loaded image object */ -static void bootefi_run_finish(struct efi_loaded_image_obj *image_obj, +static void bootefi_run_finish(efi_handle_t handle, struct efi_loaded_image *loaded_image_info) { efi_restore_gd(); free(loaded_image_info->load_options); - efi_delete_handle(&image_obj->header); + efi_delete_handle(handle); }
static int efi_handle_fdt(char *fdt_opt) @@ -319,10 +319,10 @@ static efi_status_t do_bootefi_exec(void *efi, struct efi_device_path *device_path, struct efi_device_path *image_path) { - efi_handle_t mem_handle = NULL; struct efi_device_path *memdp = NULL; + efi_handle_t handle; efi_status_t ret; - struct efi_loaded_image_obj *image_obj = NULL; + struct efi_loaded_image_obj *image_obj; struct efi_loaded_image *loaded_image_info = NULL;
EFIAPI efi_status_t (*entry)(efi_handle_t image_handle, @@ -342,28 +342,27 @@ static efi_status_t do_bootefi_exec(void *efi, * Grub expects that the device path of the loaded image is * installed on a handle. */ - ret = efi_create_handle(&mem_handle); - if (ret != EFI_SUCCESS) - return ret; /* TODO: leaks device_path */ - ret = efi_add_protocol(mem_handle, &efi_guid_device_path, - device_path); - if (ret != EFI_SUCCESS) - goto err_add_protocol; + /* + * CHECK: device path protocol will be added to handle + * in efi_setup_loaded_image() anyway. + */ } else { assert(device_path && image_path); }
ret = bootefi_run_prepare("bootargs", device_path, image_path, - &image_obj, &loaded_image_info); + &handle, &loaded_image_info); if (ret) goto err_prepare;
/* Load the EFI payload */ - entry = efi_load_pe(image_obj, efi, loaded_image_info); - if (!entry) { + image_obj = handle->platdata; + ret = efi_load_pe(image_obj, efi, loaded_image_info); + if (ret) { ret = EFI_LOAD_ERROR; goto err_prepare; } + entry = image_obj->entry;
if (memdp) { struct efi_device_path_memory *mdp = (void *)memdp; @@ -393,7 +392,7 @@ static efi_status_t do_bootefi_exec(void *efi,
/* Move into EL2 and keep running there */ armv8_switch_to_el2((ulong)entry, - (ulong)&image_obj->header, + 0, (ulong)&systab, 0, (ulong)efi_run_in_el2, ES_TO_AARCH64);
@@ -410,7 +409,7 @@ static efi_status_t do_bootefi_exec(void *efi, secure_ram_addr(_do_nonsec_entry)( efi_run_in_hyp, (uintptr_t)entry, - (uintptr_t)&image_obj->header, + 0, (uintptr_t)&systab);
/* Should never reach here, efi exits with longjmp */ @@ -418,15 +417,11 @@ static efi_status_t do_bootefi_exec(void *efi, } #endif
- ret = efi_do_enter(&image_obj->header, &systab, entry); + ret = efi_do_enter(handle, &systab, entry);
err_prepare: /* image has returned, loaded-image obj goes *poof*: */ - bootefi_run_finish(image_obj, loaded_image_info); - -err_add_protocol: - if (mem_handle) - efi_delete_handle(mem_handle); + bootefi_run_finish(handle, loaded_image_info);
return ret; } @@ -438,9 +433,7 @@ err_add_protocol: * This sets things up so we can call EFI functions. This involves preparing * the 'gd' pointer and setting up the load ed image data structures. * - * @image_objp: loaded_image_infop: Pointer to a struct which will hold the - * loaded image object. This struct will be inited by this function before - * use. + * @handlep: Pointer to a handle of the loaded image object * @loaded_image_infop: Pointer to a struct which will hold the loaded image * info. This struct will be inited by this function before use. * @path: File path to the test being run (often just the test name with a @@ -450,7 +443,7 @@ err_add_protocol: * @return 0 if OK, -ve on error */ static efi_status_t bootefi_test_prepare - (struct efi_loaded_image_obj **image_objp, + (efi_handle_t *handlep, struct efi_loaded_image **loaded_image_infop, const char *path, ulong test_func, const char *load_options_path) { @@ -465,7 +458,7 @@ static efi_status_t bootefi_test_prepare return EFI_OUT_OF_RESOURCES;
return bootefi_run_prepare(load_options_path, bootefi_device_path, - bootefi_image_path, image_objp, + bootefi_image_path, handlep, loaded_image_infop); }
@@ -558,20 +551,20 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) #endif #ifdef CONFIG_CMD_BOOTEFI_SELFTEST if (!strcmp(argv[1], "selftest")) { - struct efi_loaded_image_obj *image_obj; + efi_handle_t handle; struct efi_loaded_image *loaded_image_info;
if (efi_handle_fdt(argc > 2 ? argv[2] : NULL)) return CMD_RET_FAILURE;
- if (bootefi_test_prepare(&image_obj, &loaded_image_info, + if (bootefi_test_prepare(&handle, &loaded_image_info, "\selftest", (uintptr_t)&efi_selftest, "efi_selftest")) return CMD_RET_FAILURE;
/* Execute the test */ - r = efi_selftest(&image_obj->header, &systab); - bootefi_run_finish(image_obj, loaded_image_info); + r = efi_selftest(handle, &systab); + bootefi_run_finish(handle, loaded_image_info); return r != EFI_SUCCESS; } else #endif diff --git a/include/efi_loader.h b/include/efi_loader.h index 5882cd7dd3b0..86cf91a6feca 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -274,8 +274,8 @@ efi_status_t efi_set_watchdog(unsigned long timeout); /* Called from places to check whether a timer expired */ void efi_timer_check(void); /* PE loader implementation */ -void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, - struct efi_loaded_image *loaded_image_info); +efi_status_t efi_load_pe(struct efi_loaded_image_obj *obj, void *efi, + struct efi_loaded_image *loaded_image_info); /* Called once to store the pristine gd pointer */ void efi_save_gd(void); /* Special case handler for error/abort that just tries to dtrt to get diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index a18ce0a5705e..332dd5db199c 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -8,6 +8,7 @@ */
#include <common.h> +#include <dm.h> #include <efi_loader.h> #include <pe.h>
@@ -66,6 +67,7 @@ static efi_status_t efi_print_image_info(struct efi_loaded_image_obj *obj, if (image->file_path) printf(" '%pD'", image->file_path); printf("\n"); + return EFI_SUCCESS; }
@@ -76,17 +78,27 @@ static efi_status_t efi_print_image_info(struct efi_loaded_image_obj *obj, */ void efi_print_image_infos(void *pc) { - struct efi_object *efiobj; + struct uclass *uc; + struct udevice *dev, *protocol; + struct efi_loaded_image_obj *obj; struct efi_handler *handler; + efi_status_t ret;
- list_for_each_entry(efiobj, &efi_obj_list, link) { - list_for_each_entry(handler, &efiobj->protocols, link) { - if (!guidcmp(handler->guid, &efi_guid_loaded_image)) { - efi_print_image_info( - (struct efi_loaded_image_obj *)efiobj, - handler->protocol_interface, pc); - } - } + if (uclass_get(UCLASS_EFI_OBJECT, &uc)) + return; + + uclass_foreach_dev(dev, uc) { + if (strcmp(dev->driver->name, "efi_loaded_image")) + continue; + + ret = efi_search_protocol(dev, &efi_guid_loaded_image, + &protocol); + if (ret != EFI_SUCCESS) + continue; + + obj = dev->platdata; + handler = protocol->uclass_platdata; + efi_print_image_info(obj, handler->protocol_interface, pc); } }
@@ -198,8 +210,8 @@ static void efi_set_code_and_data_type( * piece of memory. On successful load it then returns the entry point for * the binary. Otherwise NULL. */ -void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, - struct efi_loaded_image *loaded_image_info) +efi_status_t efi_load_pe(struct efi_loaded_image_obj *obj, void *efi, + struct efi_loaded_image *loaded_image_info) { IMAGE_NT_HEADERS32 *nt; IMAGE_DOS_HEADER *dos; @@ -215,17 +227,18 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, uint64_t image_size; unsigned long virt_size = 0; int supported = 0; + efi_status_t ret;
dos = efi; if (dos->e_magic != IMAGE_DOS_SIGNATURE) { printf("%s: Invalid DOS Signature\n", __func__); - return NULL; + return EFI_INVALID_PARAMETER; }
nt = (void *) ((char *)efi + dos->e_lfanew); if (nt->Signature != IMAGE_NT_SIGNATURE) { printf("%s: Invalid NT Signature\n", __func__); - return NULL; + return EFI_INVALID_PARAMETER; }
for (i = 0; machines[i]; i++) @@ -237,7 +250,7 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, if (!supported) { printf("%s: Machine type 0x%04x is not supported\n", __func__, nt->FileHeader.Machine); - return NULL; + return EFI_UNSUPPORTED; }
/* Calculate upper virtual address boundary */ @@ -263,7 +276,7 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, if (!efi_reloc) { printf("%s: Could not allocate %lu bytes\n", __func__, virt_size); - return NULL; + return EFI_OUT_OF_RESOURCES; } entry = efi_reloc + opt->AddressOfEntryPoint; rel_size = opt->DataDirectory[rel_idx].Size; @@ -279,7 +292,7 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, if (!efi_reloc) { printf("%s: Could not allocate %lu bytes\n", __func__, virt_size); - return NULL; + return EFI_OUT_OF_RESOURCES; } entry = efi_reloc + opt->AddressOfEntryPoint; rel_size = opt->DataDirectory[rel_idx].Size; @@ -288,7 +301,7 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, } else { printf("%s: Invalid optional header magic %x\n", __func__, nt->OptionalHeader.Magic); - return NULL; + return EFI_INVALID_PARAMETER; }
/* Load sections into RAM */ @@ -302,11 +315,12 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, }
/* Run through relocations */ - if (efi_loader_relocate(rel, rel_size, efi_reloc, - (unsigned long)image_base) != EFI_SUCCESS) { + ret = efi_loader_relocate(rel, rel_size, efi_reloc, + (unsigned long)image_base); + if (ret != EFI_SUCCESS) { efi_free_pages((uintptr_t) efi_reloc, (virt_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT); - return NULL; + return ret; }
/* Flush cache */ @@ -317,8 +331,9 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, /* Populate the loaded image interface bits */ loaded_image_info->image_base = efi; loaded_image_info->image_size = image_size; - handle->reloc_base = efi_reloc; - handle->reloc_size = virt_size; + obj->reloc_base = efi_reloc; + obj->reloc_size = virt_size; + obj->entry = entry;
- return entry; + return EFI_SUCCESS; }

UCLASS_EFI will be reused later for efi root (EFI sub system itself).
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- include/dm/uclass-id.h | 3 ++- lib/efi_driver/efi_block_device.c | 2 +- lib/efi_driver/efi_uclass.c | 10 +++++----- 3 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index fb0ab40891c8..b4fca51a8192 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -39,7 +39,8 @@ 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_EFI, /* EFI sub system */ + UCLASS_EFI_DRIVER, /* EFI managed drivers */ UCLASS_EFI_OBJECT, /* EFI managed objects */ UCLASS_EFI_PROTOCOL, /* EFI managed protocols */ UCLASS_ETH, /* Ethernet device */ diff --git a/lib/efi_driver/efi_block_device.c b/lib/efi_driver/efi_block_device.c index 3f147cf60879..e0d50c866f00 100644 --- a/lib/efi_driver/efi_block_device.c +++ b/lib/efi_driver/efi_block_device.c @@ -204,6 +204,6 @@ static const struct efi_driver_ops driver_ops = { /* Identify as EFI driver */ U_BOOT_DRIVER(efi_block) = { .name = "EFI block driver", - .id = UCLASS_EFI, + .id = UCLASS_EFI_DRIVER, .ops = &driver_ops, }; diff --git a/lib/efi_driver/efi_uclass.c b/lib/efi_driver/efi_uclass.c index bb86ffd399c3..d42612a5ee03 100644 --- a/lib/efi_driver/efi_uclass.c +++ b/lib/efi_driver/efi_uclass.c @@ -307,7 +307,7 @@ efi_status_t efi_driver_init(void) debug("EFI: Initializing EFI driver framework\n"); for (drv = ll_entry_start(struct driver, driver); drv < ll_entry_end(struct driver, driver); ++drv) { - if (drv->id == UCLASS_EFI) { + if (drv->id == UCLASS_EFI_DRIVER) { ret = efi_add_driver(drv); if (ret != EFI_SUCCESS) { printf("EFI: ERROR: failed to add driver %s\n", @@ -327,7 +327,7 @@ efi_status_t efi_driver_init(void) */ static int efi_uc_init(struct uclass *class) { - printf("EFI: Initializing UCLASS_EFI\n"); + printf("EFI: Initializing UCLASS_EFI_DRIVER\n"); return 0; }
@@ -343,9 +343,9 @@ static int efi_uc_destroy(struct uclass *class) return 0; }
-UCLASS_DRIVER(efi) = { - .name = "efi", - .id = UCLASS_EFI, +UCLASS_DRIVER(efi_driver) = { + .name = "efi_driver", + .id = UCLASS_EFI_DRIVER, .init = efi_uc_init, .destroy = efi_uc_destroy, };

All the efi-specific objects, except for existing devices, will show up under "efi root node" device.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- include/efi_loader.h | 3 +++ lib/efi_loader/efi_root_node.c | 14 +++++----- lib/efi_loader/efi_setup.c | 49 +++++++++++++++++++++++++++++++++- 3 files changed, 59 insertions(+), 7 deletions(-)
diff --git a/include/efi_loader.h b/include/efi_loader.h index 86cf91a6feca..4df965455c21 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -225,6 +225,9 @@ extern struct list_head efi_obj_list; /* List of all events */ extern struct list_head efi_events;
+/* Root device */ +extern efi_handle_t efi_root; + /* Initialize efi execution environment */ efi_status_t efi_init_obj_list(void); /* Called by bootefi to initialize root node */ diff --git a/lib/efi_loader/efi_root_node.c b/lib/efi_loader/efi_root_node.c index b056ba3ee880..4b2d1457576a 100644 --- a/lib/efi_loader/efi_root_node.c +++ b/lib/efi_loader/efi_root_node.c @@ -16,6 +16,8 @@ struct efi_root_dp { struct efi_device_path end; } __packed;
+efi_handle_t efi_root; + /** * efi_root_node_register() - create root node * @@ -26,12 +28,11 @@ struct efi_root_dp { */ efi_status_t efi_root_node_register(void) { - efi_handle_t root; efi_status_t ret; struct efi_root_dp *dp;
/* Create handle */ - ret = efi_create_handle(&root); + ret = efi_add_handle(efi_root); if (ret != EFI_SUCCESS) return ret;
@@ -52,24 +53,25 @@ efi_status_t efi_root_node_register(void) dp->end.length = sizeof(struct efi_device_path);
/* Install device path protocol */ - ret = efi_add_protocol(root, &efi_guid_device_path, dp); + ret = efi_add_protocol(efi_root, &efi_guid_device_path, dp); if (ret != EFI_SUCCESS) goto failure;
/* Install device path to text protocol */ - ret = efi_add_protocol(root, &efi_guid_device_path_to_text_protocol, + ret = efi_add_protocol(efi_root, &efi_guid_device_path_to_text_protocol, (void *)&efi_device_path_to_text); if (ret != EFI_SUCCESS) goto failure;
/* Install device path utilities protocol */ - ret = efi_add_protocol(root, &efi_guid_device_path_utilities_protocol, + ret = efi_add_protocol(efi_root, + &efi_guid_device_path_utilities_protocol, (void *)&efi_device_path_utilities); if (ret != EFI_SUCCESS) goto failure;
/* Install Unicode collation protocol */ - ret = efi_add_protocol(root, &efi_guid_unicode_collation_protocol, + ret = efi_add_protocol(efi_root, &efi_guid_unicode_collation_protocol, (void *)&efi_unicode_collation_protocol); if (ret != EFI_SUCCESS) goto failure; diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index 38569af1f2c8..83f1b842e6be 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -7,6 +7,10 @@ */
#include <common.h> +#include <dm.h> +#include <dm/device-internal.h> +#include <dm/lists.h> +#include <dm/root.h> #include <efi_loader.h>
DECLARE_GLOBAL_DATA_PTR; @@ -16,7 +20,7 @@ DECLARE_GLOBAL_DATA_PTR; static efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED;
/* Initialize and populate EFI object list */ -efi_status_t efi_init_obj_list(void) +static efi_status_t efi_system_init(void) { efi_status_t ret = EFI_SUCCESS;
@@ -87,3 +91,46 @@ out: efi_obj_list_initialized = ret; return ret; } + +/* For backward compatibility */ +efi_status_t efi_init_obj_list(void) +{ + int ret; + extern struct udevice *efi_root; + + if (efi_root) + return EFI_SUCCESS; + + ret = device_bind_driver(dm_root(), "efi_root", "UEFI sub system", + &efi_root); + if (ret) + return EFI_OUT_OF_RESOURCES; + + ret = device_probe(efi_root); + if (ret) + return EFI_OUT_OF_RESOURCES; + + return EFI_SUCCESS; +} + +static int efi_system_probe(struct udevice *dev) +{ + efi_status_t ret; + + ret = efi_system_init(); + if (ret != EFI_SUCCESS) + return -1; + + return 0; +} + +U_BOOT_DRIVER(efi_root) = { + .name = "efi_root", + .id = UCLASS_EFI, + .probe = efi_system_probe, +}; + +UCLASS_DRIVER(efi) = { + .name = "efi", + .id = UCLASS_EFI, +};

Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- include/efi_loader.h | 4 +- lib/efi_loader/efi_device_path.c | 136 ++++++++++++++------- lib/efi_loader/efi_device_path_to_text.c | 55 +++++++++ lib/efi_loader/efi_device_path_utilities.c | 14 +++ 4 files changed, 164 insertions(+), 45 deletions(-)
diff --git a/include/efi_loader.h b/include/efi_loader.h index 4df965455c21..2773df4a26e9 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -386,8 +386,8 @@ extern void *efi_bounce_buffer; struct efi_device_path *efi_dp_next(const struct efi_device_path *dp); int efi_dp_match(const struct efi_device_path *a, const struct efi_device_path *b); -struct efi_object *efi_dp_find_obj(struct efi_device_path *dp, - struct efi_device_path **rem); +efi_handle_t efi_dp_find_obj(struct efi_device_path *dp, + struct efi_device_path **rem); /* get size of the first device path instance excluding end node */ efi_uintn_t efi_dp_instance_size(const struct efi_device_path *dp); /* size of multi-instance device path excluding end node */ diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index d94982314a3e..a85a2d0ff6ba 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -140,69 +140,92 @@ static struct efi_device_path *shorten_path(struct efi_device_path *dp) return dp; }
-static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path, - struct efi_device_path **rem) +struct dp_param { + struct efi_device_path *dp; + bool short_path; + struct efi_device_path **rem; + struct udevice *dev; +}; + +static int find_obj_cb(struct udevice *dev, void *arg) { - struct efi_object *efiobj; + struct dp_param *param = arg; + struct efi_device_path *dp = param->dp; + bool short_path = param->short_path; + struct efi_device_path **rem = param->rem; efi_uintn_t dp_size = efi_dp_instance_size(dp);
- list_for_each_entry(efiobj, &efi_obj_list, link) { - struct efi_handler *handler; - struct efi_device_path *obj_dp; - efi_status_t ret; - - ret = efi_search_protocol(efiobj, - &efi_guid_device_path, &handler); - if (ret != EFI_SUCCESS) - continue; - obj_dp = handler->protocol_interface; - - do { - if (efi_dp_match(dp, obj_dp) == 0) { - if (rem) { - /* - * Allow partial matches, but inform - * the caller. - */ - *rem = ((void *)dp) + - efi_dp_instance_size(obj_dp); - return efiobj; - } else { - /* Only return on exact matches */ - if (efi_dp_instance_size(obj_dp) == - dp_size) - return efiobj; - } + struct udevice *protocol; + struct efi_handler *handler; + struct efi_device_path *obj_dp; + efi_status_t ret; + + ret = efi_search_protocol(dev, &efi_guid_device_path, &protocol); + if (ret != EFI_SUCCESS) + return 0; + + handler = protocol->uclass_platdata; + obj_dp = handler->protocol_interface; + do { + if (efi_dp_match(dp, obj_dp) == 0) { + if (rem) { + /* + * Allow partial matches, but inform + * the caller. + */ + *rem = ((void *)dp) + + efi_dp_instance_size(obj_dp); + param->dev = dev; + return 1; }
- obj_dp = shorten_path(efi_dp_next(obj_dp)); - } while (short_path && obj_dp); - } + /* Only return on exact matches */ + if (efi_dp_instance_size(obj_dp) == dp_size) { + param->dev = dev; + return 1; + } + } + + obj_dp = shorten_path(efi_dp_next(obj_dp)); + } while (short_path && obj_dp); + + return 0; +} + +static struct udevice *find_obj(struct efi_device_path *dp, bool short_path, + struct efi_device_path **rem) +{ + struct dp_param dp_param; + efi_status_t ret; + + ret = efi_foreach_dev(find_obj_cb, &dp_param); + if (ret) + return NULL;
- return NULL; + return dp_param.dev; }
/* * Find an efiobj from device-path, if 'rem' is not NULL, returns the * remaining part of the device path after the matched object. */ -struct efi_object *efi_dp_find_obj(struct efi_device_path *dp, - struct efi_device_path **rem) +efi_handle_t efi_dp_find_obj(struct efi_device_path *dp, + struct efi_device_path **rem) { - struct efi_object *efiobj; + struct udevice *dev;
/* Search for an exact match first */ - efiobj = find_obj(dp, false, NULL); + dev = find_obj(dp, false, NULL);
/* Then for a fuzzy match */ - if (!efiobj) - efiobj = find_obj(dp, false, rem); + if (!dev) + dev = find_obj(dp, false, rem);
/* And now for a fuzzy short match */ - if (!efiobj) - efiobj = find_obj(dp, true, rem); + if (!dev) + dev = find_obj(dp, true, rem);
- return efiobj; + return dev; }
/* @@ -992,3 +1015,30 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr,
return EFI_SUCCESS; } + +extern +char *efi_convert_device_path_to_str(struct efi_device_path *device_path, + bool display_only, + bool allow_shortcuts); + +static int efi_device_path_probe(struct udevice *dev) +{ + struct efi_handler *handler; + struct efi_device_path *dp; + char *name; + + handler = dev->uclass_platdata; + dp = handler->protocol_interface; + name = efi_convert_device_path_to_str(dp, true, true); + device_set_name(dev, name); + + /* TODO: free at unprobe */ + + return 0; +} + +U_BOOT_DRIVER(efi_device_path) = { + .name = "efi_device_path", + .id = UCLASS_EFI_PROTOCOL, + .probe = efi_device_path_probe, +}; diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c index e219f84b28d2..3d518000eb59 100644 --- a/lib/efi_loader/efi_device_path_to_text.c +++ b/lib/efi_loader/efi_device_path_to_text.c @@ -6,6 +6,7 @@ */
#include <common.h> +#include <dm.h> #include <efi_loader.h>
#define MAC_OUTPUT_LEN 22 @@ -295,6 +296,47 @@ out: return text; }
+/* Temprarily used in probe() for device path protocol driver */ +char *efi_convert_device_path_to_str(struct efi_device_path *device_path, + bool display_only, + bool allow_shortcuts) +{ + char *text = NULL; + char buffer[MAX_PATH_LEN]; + char *str = buffer; + + if (!device_path) + goto out; + + while (device_path && + str + MAX_NODE_LEN < buffer + MAX_PATH_LEN) { + if (display_only) { + /* Only first 8 characters */ + struct efi_device_path *next; + + next = efi_dp_next(device_path); + if (next) { + device_path = next; + continue; + } + + str = efi_convert_single_device_node_to_text(str, + device_path); + str[9] = '\0'; + break; + } + + *str++ = '/'; + str = efi_convert_single_device_node_to_text(str, device_path); + device_path = efi_dp_next(device_path); + } + + text = strdup(buffer); + +out: + return text; +} + /* * This function implements the ConvertDevicePathToText service of the * EFI_DEVICE_PATH_TO_TEXT_PROTOCOL. @@ -344,3 +386,16 @@ const struct efi_device_path_to_text_protocol efi_device_path_to_text = { .convert_device_node_to_text = efi_convert_device_node_to_text, .convert_device_path_to_text = efi_convert_device_path_to_text, }; + +static int efi_device_path_to_text_probe(struct udevice *dev) +{ + device_set_name(dev, "DEVICE_PATH_TO_TEXT"); + + return 0; +} + +U_BOOT_DRIVER(efi_device_path_to_text) = { + .name = "efi_device_path_to_text", + .id = UCLASS_EFI_PROTOCOL, + .probe = efi_device_path_to_text_probe, +}; diff --git a/lib/efi_loader/efi_device_path_utilities.c b/lib/efi_loader/efi_device_path_utilities.c index 94015329c8cb..7d7f0c46b18f 100644 --- a/lib/efi_loader/efi_device_path_utilities.c +++ b/lib/efi_loader/efi_device_path_utilities.c @@ -6,6 +6,7 @@ */
#include <common.h> +#include <dm.h> #include <efi_loader.h>
const efi_guid_t efi_guid_device_path_utilities_protocol = @@ -197,3 +198,16 @@ const struct efi_device_path_utilities_protocol efi_device_path_utilities = { .is_device_path_multi_instance = is_device_path_multi_instance, .create_device_node = create_device_node, }; + +static int efi_device_path_utils_probe(struct udevice *dev) +{ + device_set_name(dev, "DEVICE_PATH_UTILITIES"); + + return 0; +} + +U_BOOT_DRIVER(efi_device_path_utils) = { + .name = "efi_device_path_utils", + .id = UCLASS_EFI_PROTOCOL, + .probe = efi_device_path_utils_probe, +};

Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- lib/efi_loader/efi_unicode_collation.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
diff --git a/lib/efi_loader/efi_unicode_collation.c b/lib/efi_loader/efi_unicode_collation.c index 7f3ea3c77e4e..9b47693d3ee5 100644 --- a/lib/efi_loader/efi_unicode_collation.c +++ b/lib/efi_loader/efi_unicode_collation.c @@ -9,6 +9,7 @@ #include <charset.h> #include <cp1250.h> #include <cp437.h> +#include <dm.h> #include <efi_loader.h>
/* Characters that may not be used in file names */ @@ -327,3 +328,21 @@ const struct efi_unicode_collation_protocol efi_unicode_collation_protocol = { .str_to_fat = efi_str_to_fat, .supported_languages = "en", }; + +static int efi_unicode_collation_probe(struct udevice *dev) +{ + struct efi_handler *handler; + struct efi_unicode_collation_protocol *col; + + handler = dev->uclass_platdata; + col = handler->protocol_interface; + device_set_name(dev, col->supported_languages); + + return 0; +} + +U_BOOT_DRIVER(efi_unicode_collation) = { + .name = "efi_unicode_collation", + .id = UCLASS_EFI_PROTOCOL, + .probe = efi_unicode_collation_probe, +};

Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- drivers/serial/serial-uclass.c | 6 ++++ lib/efi_loader/efi_console.c | 64 ++++++++++++++++++++++++++-------- lib/efi_loader/efi_setup.c | 3 -- 3 files changed, 56 insertions(+), 17 deletions(-)
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index ffcd6d15af2b..22103e313051 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -168,6 +168,12 @@ int serial_init(void) void serial_initialize(void) { serial_init(); +#if CONFIG_IS_ENABLED(EFI_LOADER) + extern int efi_console_register(void); + + if (gd->cur_serial_dev) + efi_console_register(); +#endif }
static void _serial_putc(struct udevice *dev, char ch) diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 66c33a551d5d..1d016934b494 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -12,6 +12,8 @@ #include <stdio_dev.h> #include <video_console.h>
+DECLARE_GLOBAL_DATA_PTR; + #define EFI_COUT_MODE_2 2 #define EFI_MAX_COUT_MODE 3
@@ -1051,34 +1053,29 @@ static void EFIAPI efi_key_notify(struct efi_event *event, void *context) efi_status_t efi_console_register(void) { efi_status_t r; - efi_handle_t console_output_handle; - efi_handle_t console_input_handle; + efi_handle_t handle;
/* Set up mode information */ query_console_size();
/* Create handles */ - r = efi_create_handle(&console_output_handle); + handle = gd->cur_serial_dev; + r = efi_add_handle(handle); if (r != EFI_SUCCESS) goto out_of_memory;
- r = efi_add_protocol(console_output_handle, + r = efi_add_protocol(handle, &efi_guid_text_output_protocol, &efi_con_out); if (r != EFI_SUCCESS) goto out_of_memory; - systab.con_out_handle = console_output_handle; - systab.stderr_handle = console_output_handle; - - r = efi_create_handle(&console_input_handle); - if (r != EFI_SUCCESS) - goto out_of_memory; - - r = efi_add_protocol(console_input_handle, + systab.con_out_handle = handle; + systab.stderr_handle = handle; + r = efi_add_protocol(handle, &efi_guid_text_input_protocol, &efi_con_in); if (r != EFI_SUCCESS) goto out_of_memory; - systab.con_in_handle = console_input_handle; - r = efi_add_protocol(console_input_handle, + systab.con_in_handle = handle; + r = efi_add_protocol(handle, &efi_guid_text_input_ex_protocol, &efi_con_in_ex); if (r != EFI_SUCCESS) goto out_of_memory; @@ -1107,3 +1104,42 @@ out_of_memory: printf("ERROR: Out of memory\n"); return r; } + +static int efi_simple_text_input_ex_probe(struct udevice *dev) +{ + device_set_name(dev, "SIMPLE_TEXT_INPUT_EX"); + + return 0; +} + +U_BOOT_DRIVER(efi_simple_text_input_ex) = { + .name = "efi_simple_text_input_ex", + .id = UCLASS_EFI_PROTOCOL, + .probe = efi_simple_text_input_ex_probe, +}; + +static int efi_simple_text_input_probe(struct udevice *dev) +{ + device_set_name(dev, "SIMPLE_TEXT_INPUT"); + + return 0; +} + +U_BOOT_DRIVER(efi_simple_text_input) = { + .name = "efi_simple_text_input", + .id = UCLASS_EFI_PROTOCOL, + .probe = efi_simple_text_input_probe, +}; + +static int efi_simple_text_output_probe(struct udevice *dev) +{ + device_set_name(dev, "SIMPLE_TEXT_OUTPUT"); + + return 0; +} + +U_BOOT_DRIVER(efi_simple_text_output) = { + .name = "efi_simple_text_output", + .id = UCLASS_EFI_PROTOCOL, + .probe = efi_simple_text_output_probe, +}; diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index 83f1b842e6be..a0f80948c99c 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -50,9 +50,6 @@ static efi_status_t efi_system_init(void) if (ret != EFI_SUCCESS) goto out;
- ret = efi_console_register(); - if (ret != EFI_SUCCESS) - goto out; #ifdef CONFIG_PARTITIONS ret = efi_disk_register(); if (ret != EFI_SUCCESS)

Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- lib/efi_loader/efi_net.c | 50 +++++++++++++++++++++++++++++++------- lib/efi_loader/efi_setup.c | 5 ---- net/eth-uclass.c | 5 ++++ 3 files changed, 46 insertions(+), 14 deletions(-)
diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c index c7d9da8521af..6c9b40293633 100644 --- a/lib/efi_loader/efi_net.c +++ b/lib/efi_loader/efi_net.c @@ -6,11 +6,12 @@ */
#include <common.h> +#include <dm.h> #include <efi_loader.h> #include <malloc.h>
-static const efi_guid_t efi_net_guid = EFI_SIMPLE_NETWORK_GUID; -static const efi_guid_t efi_pxe_guid = EFI_PXE_GUID; +const efi_guid_t efi_net_guid = EFI_SIMPLE_NETWORK_GUID; +const efi_guid_t efi_pxe_guid = EFI_PXE_GUID; static struct efi_pxe_packet *dhcp_ack; static bool new_rx_packet; static void *new_tx_packet; @@ -26,17 +27,16 @@ static struct efi_event *network_timer_event; */ static struct efi_event *wait_for_packet;
+/* FIXME: move this to somewhere else, like struct eth_device? */ /** * struct efi_net_obj - EFI object representing a network interface * - * @header: EFI object header * @net: simple network protocol interface * @net_mode: status of the network interface * @pxe: PXE base code protocol interface * @pxe_mode: status of the PXE base code protocol */ struct efi_net_obj { - struct efi_object header; struct efi_simple_network net; struct efi_simple_network_mode net_mode; struct efi_pxe pxe; @@ -588,10 +588,12 @@ out: */ efi_status_t efi_net_register(void) { + struct udevice *dev; struct efi_net_obj *netobj = NULL; efi_status_t r;
- if (!eth_get_dev()) { + dev = eth_get_dev(); + if (!dev) { /* No network device active, don't expose any */ return EFI_SUCCESS; } @@ -608,18 +610,22 @@ efi_status_t efi_net_register(void) transmit_buffer = (void *)ALIGN((uintptr_t)transmit_buffer, PKTALIGN);
/* Hook net up to the device list */ - efi_add_handle(&netobj->header); + r = efi_add_handle(dev); + if (r != EFI_SUCCESS) { + printf("ERROR: Failure adding net handle\n"); + return r; + }
/* Fill in object data */ - r = efi_add_protocol(&netobj->header, &efi_net_guid, + r = efi_add_protocol(dev, &efi_net_guid, &netobj->net); if (r != EFI_SUCCESS) goto failure_to_add_protocol; - r = efi_add_protocol(&netobj->header, &efi_guid_device_path, + r = efi_add_protocol(dev, &efi_guid_device_path, efi_dp_from_eth()); if (r != EFI_SUCCESS) goto failure_to_add_protocol; - r = efi_add_protocol(&netobj->header, &efi_pxe_guid, + r = efi_add_protocol(dev, &efi_pxe_guid, &netobj->pxe); if (r != EFI_SUCCESS) goto failure_to_add_protocol; @@ -691,3 +697,29 @@ out_of_resources: printf("ERROR: Out of memory\n"); return EFI_OUT_OF_RESOURCES; } + +static int efi_net_probe(struct udevice *dev) +{ + device_set_name(dev, "SIMPLE_NETWORK"); + + return 0; +} + +U_BOOT_DRIVER(efi_net) = { + .name = "efi_net", + .id = UCLASS_EFI_PROTOCOL, + .probe = efi_net_probe, +}; + +static int efi_pex_probe(struct udevice *dev) +{ + device_set_name(dev, "PXE"); + + return 0; +} + +U_BOOT_DRIVER(efi_pex) = { + .name = "efi_pex", + .id = UCLASS_EFI_PROTOCOL, + .probe = efi_pex_probe, +}; diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index a0f80948c99c..ea65dec6c066 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -60,11 +60,6 @@ static efi_status_t efi_system_init(void) if (ret != EFI_SUCCESS) goto out; #endif -#ifdef CONFIG_NET - ret = efi_net_register(); - if (ret != EFI_SUCCESS) - goto out; -#endif #ifdef CONFIG_GENERATE_ACPI_TABLE ret = efi_acpi_register(); if (ret != EFI_SUCCESS) diff --git a/net/eth-uclass.c b/net/eth-uclass.c index 91d861be4136..85830a23de32 100644 --- a/net/eth-uclass.c +++ b/net/eth-uclass.c @@ -87,6 +87,11 @@ void eth_set_dev(struct udevice *dev) }
eth_get_uclass_priv()->current = dev; +#if CONFIG_IS_ENABLED(EFI_LOADER) + extern int efi_net_register(void); + + efi_net_register(); +#endif }
/*

Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- drivers/video/video-uclass.c | 9 +++++++++ lib/efi_loader/efi_gop.c | 28 ++++++++++++++++++++++------ lib/efi_loader/efi_setup.c | 3 ++- 3 files changed, 33 insertions(+), 7 deletions(-)
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index f307cf243bdc..2abb647d4428 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -276,6 +276,15 @@ static int video_post_probe(struct udevice *dev) return ret; }
+#ifdef CONFIG_EFI_LOADER + extern efi_gop_register(void); + ret = efi_gop_register() + if (ret) { + debug("%s: Cannot register efi gop\n", __func__); + return ret; + } +#endif + return 0; };
diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c index d62ce4591272..b2ab583a44c3 100644 --- a/lib/efi_loader/efi_gop.c +++ b/lib/efi_loader/efi_gop.c @@ -14,20 +14,19 @@
DECLARE_GLOBAL_DATA_PTR;
-static const efi_guid_t efi_gop_guid = EFI_GOP_GUID; +const efi_guid_t efi_gop_guid = EFI_GOP_GUID;
+/* FIXME: move this to somewhere else, like struct video_priv? */ /** * struct efi_gop_obj - graphical output protocol object * - * @header: EFI object header * @ops: graphical output protocol interface * @info: graphical output mode information * @mode: graphical output mode * @bpix: bits per pixel * @fb: frame buffer */ -struct efi_gop_obj { - struct efi_object header; +static struct efi_gop_obj { struct efi_gop ops; struct efi_gop_mode_info info; struct efi_gop_mode mode; @@ -446,10 +445,14 @@ efi_status_t efi_gop_register(void) }
/* Hook up to the device list */ - efi_add_handle(&gopobj->header); + ret = efi_add_handle(vdev); + if (ret != EFI_SUCCESS) { + printf("ERROR: Failure adding GOP handle\n"); + return ret; + }
/* Fill in object data */ - ret = efi_add_protocol(&gopobj->header, &efi_gop_guid, + ret = efi_add_protocol(vdev, &efi_gop_guid, &gopobj->ops); if (ret != EFI_SUCCESS) { printf("ERROR: Failure adding GOP protocol\n"); @@ -489,3 +492,16 @@ efi_status_t efi_gop_register(void)
return EFI_SUCCESS; } + +static int efi_gop_probe(struct udevice *dev) +{ + device_set_name(dev, "GOP"); + + return 0; +} + +U_BOOT_DRIVER(efi_gop) = { + .name = "efi_gop", + .id = UCLASS_EFI_PROTOCOL, + .probe = efi_gop_probe, +}; diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index ea65dec6c066..59f3a617aca3 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -55,7 +55,8 @@ static efi_status_t efi_system_init(void) if (ret != EFI_SUCCESS) goto out; #endif -#if defined(CONFIG_LCD) || defined(CONFIG_DM_VIDEO) +#if defined(CONFIG_LCD) + /* for !DM_VIDEO */ ret = efi_gop_register(); if (ret != EFI_SUCCESS) goto out;

UCLASS_PARTITION device will be created as a child node of UCLASS_BLK device.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- drivers/block/blk-uclass.c | 52 ++++++++++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + 2 files changed, 53 insertions(+)
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index baaf431e5e0c..d4ca30f23fc1 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -10,6 +10,8 @@ #include <dm/device-internal.h> #include <dm/lists.h> #include <dm/uclass-internal.h> +#include <part.h> +#include <string.h>
static const char *if_typename_str[IF_TYPE_COUNT] = { [IF_TYPE_IDE] = "ide", @@ -654,3 +656,53 @@ UCLASS_DRIVER(blk) = { .post_probe = blk_post_probe, .per_device_platdata_auto_alloc_size = sizeof(struct blk_desc), }; + +U_BOOT_DRIVER(blk_partition) = { + .name = "blk_partition", + .id = UCLASS_PARTITION, + .platdata_auto_alloc_size = sizeof(struct disk_part), +}; + +UCLASS_DRIVER(partition) = { + .id = UCLASS_PARTITION, + .name = "partition", +}; + +#if defined(CONFIG_PARTITIONS) && defined(CONFIG_HAVE_BLOCK_DEVICE) +int blk_create_partitions(struct udevice *parent) +{ + int part; + struct blk_desc *desc = dev_get_uclass_platdata(parent); + disk_partition_t info; + struct disk_part *part_data; + char devname[32]; + struct udevice *dev; + int disks = 0, ret; + + /* Add devices for each partition */ + for (part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { + if (part_get_info(desc, part, &info)) + continue; + snprintf(devname, sizeof(devname), "%s:%d", parent->name, + part); + + ret = device_bind_driver(parent, "blk_partition", + strdup(devname), &dev); + if (ret) + return ret; + + part_data = dev_get_uclass_platdata(dev); + part_data->partnum = part; + part_data->gpt_part_info = info; + + disks++; + } + + return disks; +} +#else +int blk_create_partitions(struct udevice *dev) +{ + return 0; +} +#endif diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index b4fca51a8192..fce11e6d7e73 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -68,6 +68,7 @@ enum uclass_id { UCLASS_NVME, /* NVM Express device */ UCLASS_PANEL, /* Display panel, such as an LCD */ UCLASS_PANEL_BACKLIGHT, /* Backlight controller for panel */ + UCLASS_PARTITION, /* Logical disk partition device */ UCLASS_PCH, /* x86 platform controller hub */ UCLASS_PCI, /* PCI bus */ UCLASS_PCI_GENERIC, /* Generic PCI bus device */

efi_disk_create() will initialize efi_disk attributes for each device, either UCLASS_BLK or UCLASS_PARTITION, which will now be associated with efi_disk (EFI_BLOCK_IO_PROTOCOL).
Currently (temporarily), efi_disk_obj structure is embedded into blk_desc to hold efi-specific attributes.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- drivers/block/blk-uclass.c | 9 ++ include/blk.h | 24 +++++ lib/efi_loader/efi_disk.c | 216 ++++++++++++++++++++++++++----------- lib/efi_loader/efi_file.c | 14 +++ 4 files changed, 200 insertions(+), 63 deletions(-)
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index d4ca30f23fc1..28c45d724113 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -657,6 +657,9 @@ UCLASS_DRIVER(blk) = { .per_device_platdata_auto_alloc_size = sizeof(struct blk_desc), };
+/* FIXME */ +extern int efi_disk_create(struct udevice *dev); + U_BOOT_DRIVER(blk_partition) = { .name = "blk_partition", .id = UCLASS_PARTITION, @@ -695,6 +698,12 @@ int blk_create_partitions(struct udevice *parent) part_data->partnum = part; part_data->gpt_part_info = info;
+ ret = efi_disk_create(dev); + if (ret) { + device_unbind(dev); + return ret; + } + disks++; }
diff --git a/include/blk.h b/include/blk.h index d0c033aece0f..405f6f790d66 100644 --- a/include/blk.h +++ b/include/blk.h @@ -8,6 +8,7 @@ #define BLK_H
#include <efi.h> +#include <efi_api.h>
#ifdef CONFIG_SYS_64BIT_LBA typedef uint64_t lbaint_t; @@ -53,6 +54,26 @@ enum sig_type { SIG_TYPE_COUNT /* Number of signature types */ };
+/* FIXME */ +/** + * struct efi_disk_obj - EFI disk object + * + * @ops: EFI disk I/O protocol interface + * @media: block I/O media information + * @dp: device path to the block device + * @part: partition + * @volume: simple file system protocol of the partition + * @offset: offset into disk for simple partition + */ +struct efi_disk_obj { + struct efi_block_io ops; + struct efi_block_io_media media; + struct efi_device_path *dp; + unsigned int part; + struct efi_simple_file_system_protocol *volume; + lbaint_t offset; +}; + /* * With driver model (CONFIG_BLK) this is uclass platform data, accessible * with dev_get_uclass_platdata(dev) @@ -92,6 +113,9 @@ struct blk_desc { * device. Once these functions are removed we can drop this field. */ struct udevice *bdev; +#ifdef CONFIG_EFI_LOADER + struct efi_disk_obj efi_disk; +#endif #else unsigned long (*block_read)(struct blk_desc *block_dev, lbaint_t start, diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index c037526ad2d0..5e6cbb49bfb2 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -14,33 +14,6 @@
const efi_guid_t efi_block_io_guid = BLOCK_IO_GUID;
-/** - * struct efi_disk_obj - EFI disk object - * - * @header: EFI object header - * @ops: EFI disk I/O protocol interface - * @ifname: interface name for block device - * @dev_index: device index of block device - * @media: block I/O media information - * @dp: device path to the block device - * @part: partition - * @volume: simple file system protocol of the partition - * @offset: offset into disk for simple partition - * @desc: internal block device descriptor - */ -struct efi_disk_obj { - struct efi_object header; - struct efi_block_io ops; - const char *ifname; - int dev_index; - struct efi_block_io_media media; - struct efi_device_path *dp; - unsigned int part; - struct efi_simple_file_system_protocol *volume; - lbaint_t offset; - struct blk_desc *desc; -}; - static efi_status_t EFIAPI efi_disk_reset(struct efi_block_io *this, char extended_verification) { @@ -64,7 +37,7 @@ static efi_status_t efi_disk_rw_blocks(struct efi_block_io *this, unsigned long n;
diskobj = container_of(this, struct efi_disk_obj, ops); - desc = (struct blk_desc *) diskobj->desc; + desc = container_of(diskobj, struct blk_desc, efi_disk); blksz = desc->blksz; blocks = buffer_size / blksz; lba += diskobj->offset; @@ -189,7 +162,7 @@ static const struct efi_block_io block_io_disk_template = { struct efi_simple_file_system_protocol * efi_fs_from_path(struct efi_device_path *full_path) { - struct efi_object *efiobj; + struct udevice *handle, *protocol; struct efi_handler *handler; struct efi_device_path *device_path; struct efi_device_path *file_path; @@ -202,21 +175,23 @@ efi_fs_from_path(struct efi_device_path *full_path) efi_free_pool(file_path);
/* Get the EFI object for the partition */ - efiobj = efi_dp_find_obj(device_path, NULL); + handle = efi_dp_find_obj(device_path, NULL); efi_free_pool(device_path); - if (!efiobj) + if (!handle) return NULL;
/* Find the simple file system protocol */ - ret = efi_search_protocol(efiobj, &efi_simple_file_system_protocol_guid, - &handler); + ret = efi_search_protocol(handle, &efi_simple_file_system_protocol_guid, + &protocol); if (ret != EFI_SUCCESS) return NULL;
/* Return the simple file system protocol for the partition */ + handler = protocol->uclass_platdata; return handler->protocol_interface; }
+#ifndef CONFIG_BLK /* * Create a handle for a partition or disk * @@ -343,6 +318,136 @@ int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,
return disks; } +#else +static int efi_disk_create_common(efi_handle_t handle, + struct efi_disk_obj *disk, + struct blk_desc *desc) +{ + efi_status_t ret; + + /* Hook up to the device list */ + efi_add_handle(handle); + + /* Fill in EFI IO Media info (for read/write callbacks) */ + disk->media.removable_media = desc->removable; + disk->media.media_present = 1; + disk->media.block_size = desc->blksz; + disk->media.io_align = desc->blksz; + disk->media.last_block = desc->lba - disk->offset; + disk->ops.media = &disk->media; + + /* add protocols */ + disk->ops = block_io_disk_template; + ret = efi_add_protocol(handle, &efi_block_io_guid, &disk->ops); + if (ret != EFI_SUCCESS) + goto err; + + ret = efi_add_protocol(handle, &efi_guid_device_path, disk->dp); + if (ret != EFI_SUCCESS) + goto err; + + return 0; + +err: + /* FIXME: undo adding protocols */ + return -1; +} + +/* + * Create a handle for a raw disk + * + * @dev uclass device + * @return 0 on success, -1 otherwise + */ +int efi_disk_create_raw(struct udevice *dev) +{ + struct blk_desc *desc = dev_get_uclass_platdata(dev); + struct efi_disk_obj *disk = &desc->efi_disk; + + /* Don't add empty devices */ + if (!desc->lba) + return -1; + + /* raw block device */ + disk->offset = 0; + disk->part = 0; + disk->dp = efi_dp_from_part(desc, 0); + + /* efi IO media */ + disk->media.logical_partition = 0; + + return efi_disk_create_common(dev, disk, desc); +} + +/* + * Create a handle for a partition + * + * @dev uclass device + * @return 0 on success, -1 otherwise + */ +int efi_disk_create_part(struct udevice *dev) +{ + struct udevice *parent = dev->parent; + struct blk_desc *desc = dev_get_uclass_platdata(parent); + struct blk_desc *this; + struct disk_part *pdata = dev_get_uclass_platdata(dev); + struct efi_disk_obj *disk; + struct efi_device_path *node; + + int ret; + + /* dummy block device */ + this = malloc(sizeof(*this)); + if (!this) + return -1; + disk = &this->efi_disk; + + /* logical disk partition */ + disk->offset = pdata->gpt_part_info.start; + disk->part = pdata->partnum; + + node = efi_dp_part_node(desc, disk->part); + disk->dp = efi_dp_append_node(desc->efi_disk.dp, node); + efi_free_pool(node); + + /* efi IO media */ + disk->media.logical_partition = 1; + + ret = efi_disk_create_common(dev, disk, desc); + if (ret) + goto err; + + /* partition may support file system access */ + disk->volume = efi_simple_file_system(desc, disk->part, disk->dp); + ret = efi_add_protocol(dev, + &efi_simple_file_system_protocol_guid, + disk->volume); + if (ret != EFI_SUCCESS) + goto err; + + return 0; + +err: + free(this); + /* FIXME: undo create */ + + return -1; +} + +int efi_disk_create(struct udevice *dev) +{ + enum uclass_id id; + + id = device_get_uclass_id(dev); + + if (id == UCLASS_BLK) + return efi_disk_create_raw(dev); + else if (id == UCLASS_PARTITION) + return efi_disk_create_part(dev); + else + return -1; +} +#endif /* CONFIG_BLK */
/* * U-Boot doesn't have a list of all online disk devices. So when running our @@ -357,38 +462,10 @@ int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc, */ efi_status_t efi_disk_register(void) { +#ifndef CONFIG_BLK struct efi_disk_obj *disk; int disks = 0; efi_status_t ret; -#ifdef CONFIG_BLK - struct udevice *dev; - - for (uclass_first_device_check(UCLASS_BLK, &dev); dev; - uclass_next_device_check(&dev)) { - struct blk_desc *desc = dev_get_uclass_platdata(dev); - const char *if_typename = blk_get_if_type_name(desc->if_type); - - /* Add block device for the full device */ - printf("Scanning disk %s...\n", dev->name); - ret = efi_disk_add_dev(NULL, NULL, if_typename, - desc, desc->devnum, 0, 0, &disk); - if (ret == EFI_NOT_READY) { - printf("Disk %s not ready\n", dev->name); - continue; - } - if (ret) { - printf("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); - } -#else int i, if_type;
/* Search for all available disk devices */ @@ -435,8 +512,21 @@ efi_status_t efi_disk_register(void) if_typename, i, devname); } } -#endif printf("Found %d disks\n", disks); +#endif
return EFI_SUCCESS; } + +static int efi_disk_probe(struct udevice *dev) +{ + device_set_name(dev, "BLOCK_IO"); + + return 0; +} + +U_BOOT_DRIVER(efi_disk) = { + .name = "efi_disk", + .id = UCLASS_EFI_PROTOCOL, + .probe = efi_disk_probe, +}; diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c index 128cb0a6273a..ec306fb8ca4f 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -7,6 +7,7 @@
#include <common.h> #include <charset.h> +#include <dm.h> #include <efi_loader.h> #include <malloc.h> #include <mapmem.h> @@ -708,3 +709,16 @@ efi_simple_file_system(struct blk_desc *desc, int part,
return &fs->base; } + +static int efi_simple_file_system_probe(struct udevice *dev) +{ + device_set_name(dev, "SIMPLE_FILE_SYSTEM"); + + return 0; +} + +U_BOOT_DRIVER(efi_simple_file_system) = { + .name = "efi_simple_file_system", + .id = UCLASS_EFI_PROTOCOL, + .probe = efi_simple_file_system_probe, +};

Efi_disk_create() should be hook up at every creation of block device at each driver. Associated blk_desc must be properly set up before calling this function.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- common/usb_storage.c | 27 +++++++++++++++++++++++++-- drivers/scsi/scsi.c | 22 ++++++++++++++++++++++ lib/efi_driver/efi_block_device.c | 30 +++++++++--------------------- 3 files changed, 56 insertions(+), 23 deletions(-)
diff --git a/common/usb_storage.c b/common/usb_storage.c index 8c889bb1a648..ff895c0e4557 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -46,6 +46,10 @@ #include <part.h> #include <usb.h>
+/* FIXME */ +extern int efi_disk_create(struct udevice *dev); +extern int blk_create_partitions(struct udevice *parent); + #undef BBB_COMDAT_TRACE #undef BBB_XPORT_TRACE
@@ -227,8 +231,27 @@ static int usb_stor_probe_device(struct usb_device *udev)
ret = usb_stor_get_info(udev, data, blkdev); if (ret == 1) { - usb_max_devs++; - debug("%s: Found device %p\n", __func__, udev); + ret = efi_disk_create(dev); + if (ret) { + debug("Cannot create efi_disk device\n"); + ret = device_unbind(dev); + if (ret) + return ret; + } else { + usb_max_devs++; + ret = blk_create_partitions(dev); + if (ret < 0) { + debug("Cannot create disk partition device\n"); + /* TODO: undo create */ + + ret = device_unbind(dev); + if (ret) + return ret; + } + usb_max_devs += ret; + debug("%s: Found device %p, partitions:%d\n", + __func__, udev, ret); + } } else { debug("usb_stor_get_info: Invalid device\n"); ret = device_unbind(dev); diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index df47e2fc78bd..f0f8cbc0bf26 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -11,6 +11,10 @@ #include <dm/device-internal.h> #include <dm/uclass-internal.h>
+/* FIXME */ +int efi_disk_create(struct udevice *dev); +int blk_create_partitions(struct udevice *parent); + #if !defined(CONFIG_DM_SCSI) # ifdef CONFIG_SCSI_DEV_LIST # define SCSI_DEV_LIST CONFIG_SCSI_DEV_LIST @@ -593,9 +597,27 @@ static int do_scsi_scan_one(struct udevice *dev, int id, int lun, bool verbose) memcpy(&bdesc->product, &bd.product, sizeof(bd.product)); memcpy(&bdesc->revision, &bd.revision, sizeof(bd.revision));
+ ret = efi_disk_create(bdev); + if (ret) { + debug("Can't create efi_disk device\n"); + ret = device_unbind(bdev); + + return ret; + } + ret = blk_create_partitions(bdev); + if (ret < 0) { + debug("Can't create efi_disk partitions\n"); + /* TODO: undo create */ + + ret = device_unbind(bdev); + + return ret; + } + if (verbose) { printf(" Device %d: ", 0); dev_print(bdesc); + debug("Found %d partitions\n", ret); } return 0; } diff --git a/lib/efi_driver/efi_block_device.c b/lib/efi_driver/efi_block_device.c index e0d50c866f00..acef1b20867e 100644 --- a/lib/efi_driver/efi_block_device.c +++ b/lib/efi_driver/efi_block_device.c @@ -32,6 +32,10 @@ #include <dm/device-internal.h> #include <dm/root.h>
+/* FIXME */ +extern int efi_disk_create(struct udevice *dev); +extern int blk_create_partitions(struct udevice *parent); + /* * EFI attributes of the udevice handled by this driver. * @@ -102,24 +106,6 @@ static ulong efi_bl_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, return blkcnt; }
-/* - * Create partions for the block device. - * - * @handle EFI handle of the block device - * @dev udevice of the block device - */ -static int efi_bl_bind_partitions(efi_handle_t handle, struct udevice *dev) -{ - struct blk_desc *desc; - const char *if_typename; - - desc = dev_get_uclass_platdata(dev); - if_typename = blk_get_if_type_name(desc->if_type); - - return efi_disk_create_partitions(handle, desc, if_typename, - desc->devnum, dev->name); -} - /* * Create a block device for a handle * @@ -168,15 +154,17 @@ static int efi_bl_bind(efi_handle_t handle, void *interface) platdata->handle = handle; platdata->io = interface;
+ ret = efi_disk_create(bdev); + if (ret) + return ret; + ret = device_probe(bdev); if (ret) return ret; EFI_PRINT("%s: block device '%s' created\n", __func__, bdev->name); - /* Create handles for the partions of the block device */ - disks = efi_bl_bind_partitions(handle, bdev); + disks = blk_create_partitions(bdev); EFI_PRINT("Found %d partitions\n", disks); - return 0; }

Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- lib/efi_driver/efi_block_device.c | 4 ---- lib/efi_driver/efi_uclass.c | 27 ++++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 5 deletions(-)
diff --git a/lib/efi_driver/efi_block_device.c b/lib/efi_driver/efi_block_device.c index acef1b20867e..f3e7ebf6dc5e 100644 --- a/lib/efi_driver/efi_block_device.c +++ b/lib/efi_driver/efi_block_device.c @@ -118,16 +118,12 @@ static int efi_bl_bind(efi_handle_t handle, void *interface) struct udevice *bdev, *parent = dm_root(); int ret, devnum; char *name; - struct efi_object *obj = efi_search_obj(handle); struct efi_block_io *io = interface; int disks; struct efi_blk_platdata *platdata;
EFI_PRINT("%s: handle %p, interface %p\n", __func__, handle, io);
- if (!obj) - return -ENOENT; - devnum = blk_find_max_devnum(IF_TYPE_EFI); if (devnum == -ENODEV) devnum = 0; diff --git a/lib/efi_driver/efi_uclass.c b/lib/efi_driver/efi_uclass.c index d42612a5ee03..bf6bc79837ba 100644 --- a/lib/efi_driver/efi_uclass.c +++ b/lib/efi_driver/efi_uclass.c @@ -18,6 +18,8 @@ */
#include <efi_driver.h> +#include <dm/device-internal.h> +#include <dm/lists.h>
/** * check_node_type() - check node type @@ -272,8 +274,18 @@ static efi_status_t efi_add_driver(struct driver *drv) bp->bp.version = 0xffffffff; bp->ops = drv->ops;
- ret = efi_create_handle(&bp->bp.driver_binding_handle); + ret = device_bind_driver(efi_root, drv->name, drv->name, + &bp->bp.driver_binding_handle); + if (ret) { + free(bp); + goto out; + } + + ret = efi_add_handle(bp->bp.driver_binding_handle); if (ret != EFI_SUCCESS) { +#ifdef CONFIG_DM_DEVICE_REMOVE + device_unbind(bp->bp.driver_binding_handle); +#endif free(bp); goto out; } @@ -349,3 +361,16 @@ UCLASS_DRIVER(efi_driver) = { .init = efi_uc_init, .destroy = efi_uc_destroy, }; + +static int efi_driver_binding_probe(struct udevice *dev) +{ + device_set_name(dev, "DRIVER_BINDING"); + + return 0; +} + +U_BOOT_DRIVER(efi_driver_binding) = { + .name = "efi_driver_binding", + .id = UCLASS_EFI_PROTOCOL, + .probe = efi_driver_binding_probe, +};

Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- cmd/efidebug.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/cmd/efidebug.c b/cmd/efidebug.c index 39398669e18f..e1c3628f72fb 100644 --- a/cmd/efidebug.c +++ b/cmd/efidebug.c @@ -8,6 +8,7 @@ #include <charset.h> #include <common.h> #include <command.h> +#include <dm.h> #include <efi_loader.h> #include <environment.h> #include <exports.h> @@ -114,6 +115,7 @@ static int do_efi_show_devices(cmd_tbl_t *cmdtp, int flag, static int efi_get_driver_handle_info(efi_handle_t handle, u16 **driver_name, u16 **image_path) { + struct udevice *protocol; struct efi_handler *handler; struct efi_loaded_image *image; efi_status_t ret; @@ -125,12 +127,13 @@ static int efi_get_driver_handle_info(efi_handle_t handle, u16 **driver_name, *driver_name = NULL;
/* image name */ - ret = efi_search_protocol(handle, &efi_guid_loaded_image, &handler); + ret = efi_search_protocol(handle, &efi_guid_loaded_image, &protocol); if (ret != EFI_SUCCESS) { *image_path = NULL; return 0; }
+ handler = protocol->uclass_platdata; image = handler->protocol_interface; *image_path = efi_dp_str(image->file_path);

On 2/8/19 9:15 AM, AKASHI Takahiro wrote:
# bootefi doesn't work with this patch set yet
This patch set came from the past discussion[1] on my "removable device support" patch and is intended to be an attempt to integrate efi objects into u-boot's Driver Model as much seamlessly as possible.
[1] https://lists.denx.de/pipermail/u-boot/2019-January/354010.html
Since this patch is a prototype (or POC, Proof-Of-Concept), the aim here is to discuss further about how in a better shape we will be able to merge the two worlds.
After RFC, Simon suggested that efi protocols could be also presented as DM devices. This is a major change in RFC v2.
Hello Takahiro,
thanks a lot for laying out your thoughts about a possible integration of the EFI subsystem and the driver model. Thanks also for providing a first implementation.
Basic idea is
- efi_root is a DM device
- Any efi object, refered to by efi_handle_t in UEFI world, has a corresponding DM device.
EFI applications and drivers will create handles having no relation to the U-Boot world.
- define efi_handle_t as "struct udevice *"
An EFI handle does not necessarily relate to any U-Boot device. Why should a handle which has not backing device carry the extra fields of struct udevice?
- for efi_disk,
- add "struct efi_disk_obj" to blk_desc
struct efi_disk_obj * is currently the handle of the block device. So you only some fields may be moved to blk_desc. But I guess I will find that in one of the patches.
- for the objects below, there is only one instance for each and so they are currently global data: efi_gop_obj, efi_net_obj,
efi_net_obj * is the handle of the network device. In future we should support multiple network devices.
simple_text_output_mode
- for loaded_image,
- link efi_loaded_image_obj to device's platdata
An EFI application can create an image out of "nothing". Just create a handle with InstallProtocolInterface() and then call LoadImage() with a pointer to some place in memory.
Many images loaded from the same device may be present at the same time, e.g. iPXE, GRUB, and Linux.
- Any efi protocol has a corresponding DM device.
Protocol implementations are not only provided by U-Boot but also by EFI applications and driver binaries. And of cause the EFI binaries will implement a lot of protocols completely unknown to U-Boot. So what should be the meaning of the above sentence in this context?
Above you suggested that struct udevice * would be used as a handle. So on which handle is the protocol now installed in your model?
For a protocol like the device path protocol which is only a data structure with no related function modules I do not understand the benefit of creating a separate sub-device.
- link "struct efi_handler" to device's uclass_platdata
struct efi_handler is an item in the list of protocols installed on a handle. For some of the protocols installed by an EFI application there will not be any corresponding uclass.
- be a child of a efi object (hence DM device) in DM device hierarchy so that enumerating protocols belonging to efi object is done by traversing the tree.
Above you said a struct udevice * would be a handle. So here you imply that for each protocol interface you will create an extra handle. That does not fit the EFI model.
- Any efi object which has a backing DM device should be created when that DM device is detected (and probed).
Detected or probed? This is not the same.
- For efi_disk (or any object with EFI_BLOCK_IO_PROTOCOL),
- add UCLASS_PARTITION
- put partitions under a raw block device
- partitions as well as raw devices can be efi_disk
Agreed.
With those extensive changes, there still exists plenty of "wrapper" code. Do you have any idea to reduce it?
The concept presented does not cover:
- device, drivers, protocols created by EFI applications and driver binaries - non-DM drivers and devices in U-Boot
It creates extra handles per installed protocol interface which should not exist in the EFI world.
So some rework of the concept is needed.
I suggest to start smaller:
- convert partitions to the DM model. - provide a pointer serving as EFI handle in struct udevice
Best regards
Heinrich
***** Example operation ****** (Two scsi disks, one with no partition, one with two partitions)
=> efi dev EFI: Initializing UCLASS_EFI_DRIVER Device Device Path ================ ==================== 000000007eef9470 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b) => scsi rescan
Reset SCSI scanning bus for devices... Target spinup took 0 ms. Target spinup took 0 ms. SATA link 2 timeout. SATA link 3 timeout. SATA link 4 timeout. SATA link 5 timeout. AHCI 0001.0000 32 slots 6 ports 1.5 Gbps 0x3f impl SATA mode flags: 64bit ncq only Device 0: (0:0) Vendor: ATA Prod.: QEMU HARDDISK Rev: 2.5+ Type: Hard Disk Capacity: 16.0 MB = 0.0 GB (32768 x 512) Device 0: (1:0) Vendor: ATA Prod.: QEMU HARDDISK Rev: 2.5+ Type: Hard Disk Capacity: 256.0 MB = 0.2 GB (524288 x 512) => efi dev Device Device Path ================ ==================== 000000007eef9470 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b) 000000007ef01c90 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(0,0) 000000007ef04910 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(1,0) 000000007ef04ee0 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(1,0)/HD(335544330,MBR,0x086246ba,0x17ff4f1a0,0x7eee3770) 000000007ef055a0 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(1,0)/HD(335544330,MBR,0x086246ba,0x17ff4f1a0,0x7eee3770) => dm tree Class index Probed Driver Name
root 0 [ + ] root_driver root_driver simple_bus 0 [ ] generic_simple_bus |-- platform@c000000 virtio 0 [ + ] virtio-mmio |-- virtio_mmio@a000000
[snip]
pci 0 [ + ] pci_generic_ecam |-- pcie@10000000 pci_generi 0 [ ] pci_generic_drv | |-- pci_0:0.0 virtio 32 [ ] virtio-pci.l | |-- virtio-pci.l#0 ahci 0 [ + ] ahci_pci | `-- ahci_pci scsi 0 [ + ] ahci_scsi | `-- ahci_scsi blk 0 [ + ] scsi_blk | |-- ahci_scsi.id0lun0 efi_protoc 8 [ + ] efi_disk | | |-- BLOCK_IO efi_protoc 9 [ + ] efi_device_path | | `-- Scsi(0,0) blk 1 [ + ] scsi_blk | `-- ahci_scsi.id1lun0 efi_protoc 10 [ + ] efi_disk | |-- BLOCK_IO efi_protoc 11 [ + ] efi_device_path | |-- Scsi(1,0) partition 0 [ + ] blk_partition | |-- ahci_scsi.id1lun0:1 efi_protoc 12 [ + ] efi_disk | | |-- BLOCK_IO efi_protoc 13 [ + ] efi_device_path | | |-- HD(335544330,MBR,0x086246ba,0x17ff4f1a0,0x7eee3770) efi_protoc 14 [ + ] efi_simple_file_syst | | `-- SIMPLE_FILE_SYSTEM partition 1 [ + ] blk_partition | `-- ahci_scsi.id1lun0:2 efi_protoc 15 [ + ] efi_disk | |-- BLOCK_IO efi_protoc 16 [ + ] efi_device_path | |-- HD(335544330,MBR,0x086246ba,0x17ff4f1a0,0x7eee3770) efi_protoc 17 [ + ] efi_simple_file_syst | `-- SIMPLE_FILE_SYSTEM rtc 0 [ ] rtc-pl031 |-- pl031@9010000 serial 0 [ ] serial_pl01x |-- pl011@9050000 serial 1 [ + ] serial_pl01x |-- pl011@9000000 efi_protoc 0 [ + ] efi_simple_text_outp | |-- SIMPLE_TEXT_OUTPUT efi_protoc 1 [ + ] efi_simple_text_inpu | |-- SIMPLE_TEXT_INPUT efi_protoc 2 [ + ] efi_simple_text_inpu | `-- SIMPLE_TEXT_INPUT_EX mtd 0 [ + ] cfi_flash |-- flash@0 firmware 0 [ + ] psci |-- psci sysreset 0 [ ] psci-sysreset | `-- psci-sysreset efi 0 [ + ] efi_root `-- UEFI sub system efi_protoc 3 [ + ] efi_device_path |-- VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b) efi_protoc 4 [ + ] efi_device_path_to_t |-- DEVICE_PATH_TO_TEXT efi_protoc 5 [ + ] efi_device_path_util |-- DEVICE_PATH_UTILITIES efi_protoc 6 [ + ] efi_unicode_collatio |-- en efi_driver 0 [ + ] EFI block driver `-- EFI block driver efi_protoc 7 [ + ] efi_driver_binding `-- DRIVER_BINDING
Thanks, -Takahiro Akashi
AKASHI Takahiro (15): efi_loader: efi objects and protocols as DM devices efi_loader: boottime: convert efi_loaded_image_obj to DM efi_loader: image_loader: aligned with DM efi_driver: rename UCLASS_EFI to UCLASS_EFI_DRIVER efi_loader: convert efi_root_node to DM efi_loader: device path: convert efi_device_path to DM efi_loader: unicode_collation: converted to DM efi_loader: console: convert efi console input/output to DM efi_loader: net: convert efi_net_obj to DM efi_loader: gop: convert efi_gop_obj to DM dm: blk: add UCLASS_PARTITION efi_loader: disk: convert efi_disk_obj to DM drivers: align block device drivers with DM-efi integration efi_driver: converted to DM cmd: efidebug: aligned with DM-efi integration
cmd/bootefi.c | 61 +-- cmd/efidebug.c | 5 +- common/usb_storage.c | 27 +- drivers/block/blk-uclass.c | 61 +++ drivers/scsi/scsi.c | 22 + drivers/serial/serial-uclass.c | 6 + drivers/video/video-uclass.c | 9 + include/blk.h | 24 + include/dm/device.h | 3 + include/dm/uclass-id.h | 6 +- include/efi.h | 4 +- include/efi_loader.h | 50 +- lib/efi_driver/efi_block_device.c | 36 +- lib/efi_driver/efi_uclass.c | 37 +- lib/efi_loader/efi_boottime.c | 605 ++++++++++++++------- lib/efi_loader/efi_console.c | 64 ++- lib/efi_loader/efi_device_path.c | 136 +++-- lib/efi_loader/efi_device_path_to_text.c | 55 ++ lib/efi_loader/efi_device_path_utilities.c | 14 + lib/efi_loader/efi_disk.c | 216 +++++--- lib/efi_loader/efi_file.c | 14 + lib/efi_loader/efi_gop.c | 28 +- lib/efi_loader/efi_image_loader.c | 61 ++- lib/efi_loader/efi_net.c | 50 +- lib/efi_loader/efi_root_node.c | 14 +- lib/efi_loader/efi_setup.c | 60 +- lib/efi_loader/efi_unicode_collation.c | 19 + net/eth-uclass.c | 5 + 28 files changed, 1226 insertions(+), 466 deletions(-)

Hi Heinrich,
On Fri, 8 Feb 2019 at 03:36, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 2/8/19 9:15 AM, AKASHI Takahiro wrote:
# bootefi doesn't work with this patch set yet
This patch set came from the past discussion[1] on my "removable device support" patch and is intended to be an attempt to integrate efi objects into u-boot's Driver Model as much seamlessly as possible.
[1] https://lists.denx.de/pipermail/u-boot/2019-January/354010.html
Since this patch is a prototype (or POC, Proof-Of-Concept), the aim here is to discuss further about how in a better shape we will be able to merge the two worlds.
After RFC, Simon suggested that efi protocols could be also presented as DM devices. This is a major change in RFC v2.
Hello Takahiro,
thanks a lot for laying out your thoughts about a possible integration of the EFI subsystem and the driver model. Thanks also for providing a first implementation.
Yes indeed. It is very clever what you have been able to do Takahiro.
Basic idea is
- efi_root is a DM device
- Any efi object, refered to by efi_handle_t in UEFI world, has a corresponding DM device.
EFI applications and drivers will create handles having no relation to the U-Boot world.
I suggest that we change that, i.e. that all devices in existence have a struct udevice. That way DM knows about everything and we don't have the strange parallel 'EFI' world. I don't see any need for it.
- define efi_handle_t as "struct udevice *"
An EFI handle does not necessarily relate to any U-Boot device. Why should a handle which has not backing device carry the extra fields of struct udevice?
Because this is the U-Boot driver model. We should not have an EFI parallel to DM and certainly not just to save a few dozen bytes of data space. If you were trying to save data space, you would not use EFI :-)
- for efi_disk,
- add "struct efi_disk_obj" to blk_desc
struct efi_disk_obj * is currently the handle of the block device. So you only some fields may be moved to blk_desc. But I guess I will find that in one of the patches.
- for the objects below, there is only one instance for each and so they are currently global data: efi_gop_obj, efi_net_obj,
efi_net_obj * is the handle of the network device. In future we should support multiple network devices.
simple_text_output_mode
- for loaded_image,
- link efi_loaded_image_obj to device's platdata
An EFI application can create an image out of "nothing". Just create a handle with InstallProtocolInterface() and then call LoadImage() with a pointer to some place in memory.
Many images loaded from the same device may be present at the same time, e.g. iPXE, GRUB, and Linux.
- Any efi protocol has a corresponding DM device.
Protocol implementations are not only provided by U-Boot but also by EFI applications and driver binaries. And of cause the EFI binaries will implement a lot of protocols completely unknown to U-Boot. So what should be the meaning of the above sentence in this context?
Can we instead add a uclass for each EFI protocol? Then U-Boot does know about them.
Above you suggested that struct udevice * would be used as a handle. So on which handle is the protocol now installed in your model?
For a protocol like the device path protocol which is only a data structure with no related function modules I do not understand the benefit of creating a separate sub-device.
I think it is only a matter of convenience and to keep things regular.
- link "struct efi_handler" to device's uclass_platdata
struct efi_handler is an item in the list of protocols installed on a handle. For some of the protocols installed by an EFI application there will not be any corresponding uclass.
As above, perhaps we should fix that?
- be a child of a efi object (hence DM device) in DM device hierarchy so that enumerating protocols belonging to efi object is done by traversing the tree.
Above you said a struct udevice * would be a handle. So here you imply that for each protocol interface you will create an extra handle. That does not fit the EFI model.
- Any efi object which has a backing DM device should be created when that DM device is detected (and probed).
Detected or probed? This is not the same.
- For efi_disk (or any object with EFI_BLOCK_IO_PROTOCOL),
- add UCLASS_PARTITION
- put partitions under a raw block device
- partitions as well as raw devices can be efi_disk
Agreed.
With those extensive changes, there still exists plenty of "wrapper" code. Do you have any idea to reduce it?
The concept presented does not cover:
- device, drivers, protocols created by EFI applications and driver binaries
Can we create uclasses for each 'protocol'? Is there any reason why we cannot?
- non-DM drivers and devices in U-Boot
This doesn't really matter as they will be gone soon. At the risk of repeating myself, EFI support should never have supported non-DM in the first place. It was not the right decision, in my view.
It creates extra handles per installed protocol interface which should not exist in the EFI world.
So some rework of the concept is needed.
I suggest to start smaller:
- convert partitions to the DM model.
This is in later patches from what I can tell.
- provide a pointer serving as EFI handle in struct udevice
I actually feel that the approach here, while admittedly bold, seems to be a good step forward.
Regards, Simon
Best regards
Heinrich
***** Example operation ****** (Two scsi disks, one with no partition, one with two partitions)
=> efi dev EFI: Initializing UCLASS_EFI_DRIVER Device Device Path ================ ==================== 000000007eef9470 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b) => scsi rescan
Reset SCSI scanning bus for devices... Target spinup took 0 ms. Target spinup took 0 ms. SATA link 2 timeout. SATA link 3 timeout. SATA link 4 timeout. SATA link 5 timeout. AHCI 0001.0000 32 slots 6 ports 1.5 Gbps 0x3f impl SATA mode flags: 64bit ncq only Device 0: (0:0) Vendor: ATA Prod.: QEMU HARDDISK Rev: 2.5+ Type: Hard Disk Capacity: 16.0 MB = 0.0 GB (32768 x 512) Device 0: (1:0) Vendor: ATA Prod.: QEMU HARDDISK Rev: 2.5+ Type: Hard Disk Capacity: 256.0 MB = 0.2 GB (524288 x 512) => efi dev Device Device Path ================ ==================== 000000007eef9470 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b) 000000007ef01c90 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(0,0) 000000007ef04910 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(1,0) 000000007ef04ee0 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(1,0)/HD(335544330,MBR,0x086246ba,0x17ff4f1a0,0x7eee3770) 000000007ef055a0 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(1,0)/HD(335544330,MBR,0x086246ba,0x17ff4f1a0,0x7eee3770) => dm tree Class index Probed Driver Name
root 0 [ + ] root_driver root_driver simple_bus 0 [ ] generic_simple_bus |-- platform@c000000 virtio 0 [ + ] virtio-mmio |-- virtio_mmio@a000000
[snip]
pci 0 [ + ] pci_generic_ecam |-- pcie@10000000 pci_generi 0 [ ] pci_generic_drv | |-- pci_0:0.0 virtio 32 [ ] virtio-pci.l | |-- virtio-pci.l#0 ahci 0 [ + ] ahci_pci | `-- ahci_pci scsi 0 [ + ] ahci_scsi | `-- ahci_scsi blk 0 [ + ] scsi_blk | |-- ahci_scsi.id0lun0 efi_protoc 8 [ + ] efi_disk | | |-- BLOCK_IO efi_protoc 9 [ + ] efi_device_path | | `-- Scsi(0,0) blk 1 [ + ] scsi_blk | `-- ahci_scsi.id1lun0 efi_protoc 10 [ + ] efi_disk | |-- BLOCK_IO efi_protoc 11 [ + ] efi_device_path | |-- Scsi(1,0) partition 0 [ + ] blk_partition | |-- ahci_scsi.id1lun0:1 efi_protoc 12 [ + ] efi_disk | | |-- BLOCK_IO efi_protoc 13 [ + ] efi_device_path | | |-- HD(335544330,MBR,0x086246ba,0x17ff4f1a0,0x7eee3770) efi_protoc 14 [ + ] efi_simple_file_syst | | `-- SIMPLE_FILE_SYSTEM partition 1 [ + ] blk_partition | `-- ahci_scsi.id1lun0:2 efi_protoc 15 [ + ] efi_disk | |-- BLOCK_IO efi_protoc 16 [ + ] efi_device_path | |-- HD(335544330,MBR,0x086246ba,0x17ff4f1a0,0x7eee3770) efi_protoc 17 [ + ] efi_simple_file_syst | `-- SIMPLE_FILE_SYSTEM rtc 0 [ ] rtc-pl031 |-- pl031@9010000 serial 0 [ ] serial_pl01x |-- pl011@9050000 serial 1 [ + ] serial_pl01x |-- pl011@9000000 efi_protoc 0 [ + ] efi_simple_text_outp | |-- SIMPLE_TEXT_OUTPUT efi_protoc 1 [ + ] efi_simple_text_inpu | |-- SIMPLE_TEXT_INPUT efi_protoc 2 [ + ] efi_simple_text_inpu | `-- SIMPLE_TEXT_INPUT_EX mtd 0 [ + ] cfi_flash |-- flash@0 firmware 0 [ + ] psci |-- psci sysreset 0 [ ] psci-sysreset | `-- psci-sysreset efi 0 [ + ] efi_root `-- UEFI sub system efi_protoc 3 [ + ] efi_device_path |-- VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b) efi_protoc 4 [ + ] efi_device_path_to_t |-- DEVICE_PATH_TO_TEXT efi_protoc 5 [ + ] efi_device_path_util |-- DEVICE_PATH_UTILITIES efi_protoc 6 [ + ] efi_unicode_collatio |-- en efi_driver 0 [ + ] EFI block driver `-- EFI block driver efi_protoc 7 [ + ] efi_driver_binding `-- DRIVER_BINDING
Thanks, -Takahiro Akashi
AKASHI Takahiro (15): efi_loader: efi objects and protocols as DM devices efi_loader: boottime: convert efi_loaded_image_obj to DM efi_loader: image_loader: aligned with DM efi_driver: rename UCLASS_EFI to UCLASS_EFI_DRIVER efi_loader: convert efi_root_node to DM efi_loader: device path: convert efi_device_path to DM efi_loader: unicode_collation: converted to DM efi_loader: console: convert efi console input/output to DM efi_loader: net: convert efi_net_obj to DM efi_loader: gop: convert efi_gop_obj to DM dm: blk: add UCLASS_PARTITION efi_loader: disk: convert efi_disk_obj to DM drivers: align block device drivers with DM-efi integration efi_driver: converted to DM cmd: efidebug: aligned with DM-efi integration
cmd/bootefi.c | 61 +-- cmd/efidebug.c | 5 +- common/usb_storage.c | 27 +- drivers/block/blk-uclass.c | 61 +++ drivers/scsi/scsi.c | 22 + drivers/serial/serial-uclass.c | 6 + drivers/video/video-uclass.c | 9 + include/blk.h | 24 + include/dm/device.h | 3 + include/dm/uclass-id.h | 6 +- include/efi.h | 4 +- include/efi_loader.h | 50 +- lib/efi_driver/efi_block_device.c | 36 +- lib/efi_driver/efi_uclass.c | 37 +- lib/efi_loader/efi_boottime.c | 605 ++++++++++++++------- lib/efi_loader/efi_console.c | 64 ++- lib/efi_loader/efi_device_path.c | 136 +++-- lib/efi_loader/efi_device_path_to_text.c | 55 ++ lib/efi_loader/efi_device_path_utilities.c | 14 + lib/efi_loader/efi_disk.c | 216 +++++--- lib/efi_loader/efi_file.c | 14 + lib/efi_loader/efi_gop.c | 28 +- lib/efi_loader/efi_image_loader.c | 61 ++- lib/efi_loader/efi_net.c | 50 +- lib/efi_loader/efi_root_node.c | 14 +- lib/efi_loader/efi_setup.c | 60 +- lib/efi_loader/efi_unicode_collation.c | 19 + net/eth-uclass.c | 5 + 28 files changed, 1226 insertions(+), 466 deletions(-)

Hi Heinrich, Simon,
On Sat, Feb 09, 2019 at 05:00:33PM -0600, Simon Glass wrote:
Hi Heinrich,
On Fri, 8 Feb 2019 at 03:36, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 2/8/19 9:15 AM, AKASHI Takahiro wrote:
# bootefi doesn't work with this patch set yet
This patch set came from the past discussion[1] on my "removable device support" patch and is intended to be an attempt to integrate efi objects into u-boot's Driver Model as much seamlessly as possible.
[1] https://lists.denx.de/pipermail/u-boot/2019-January/354010.html
Since this patch is a prototype (or POC, Proof-Of-Concept), the aim here is to discuss further about how in a better shape we will be able to merge the two worlds.
After RFC, Simon suggested that efi protocols could be also presented as DM devices. This is a major change in RFC v2.
Hello Takahiro,
thanks a lot for laying out your thoughts about a possible integration of the EFI subsystem and the driver model. Thanks also for providing a first implementation.
Yes indeed. It is very clever what you have been able to do Takahiro.
I think that I'm going to extremes here :)
I wonder what the EFI world will look like if all the handles and protocols are also DM devices. I don't expect that my patch will be upstreamed any time soon (or possibly forever not) So, instead of claiming the change would be meaningless, I'd welcome any suggestions, like what will happen if we merge/integrate EFI's A with U-Boot's B?
I'm willing to make best efforts to give such an idea a reality if possible. Then choices come after that.
Basic idea is
- efi_root is a DM device
- Any efi object, refered to by efi_handle_t in UEFI world, has a corresponding DM device.
EFI applications and drivers will create handles having no relation to the U-Boot world.
I suggest that we change that, i.e. that all devices in existence have a struct udevice. That way DM knows about everything and we don't have the strange parallel 'EFI' world. I don't see any need for it.
Simply, it would be nice that we can list all the applications and drivers loaded at one place, akin to linux's * ls /proc/ * cat /proc/modules
(From the viewpoint of API, we can do that just by calling locate_handle(BY_PROTOCOL, EFI_LOADED_IMAGE, ...) though.)
- define efi_handle_t as "struct udevice *"
An EFI handle does not necessarily relate to any U-Boot device. Why should a handle which has not backing device carry the extra fields of struct udevice?
Because this is the U-Boot driver model. We should not have an EFI parallel to DM and certainly not just to save a few dozen bytes of data space. If you were trying to save data space, you would not use EFI :-)
Ah, thank you.
From a viewpoint of implementation, the situation where some handles
are DM devices and some are not could make the efi code, particularly boottime.c, quite ugly and complicated.
- for efi_disk,
- add "struct efi_disk_obj" to blk_desc
struct efi_disk_obj * is currently the handle of the block device. So you only some fields may be moved to blk_desc. But I guess I will find that in one of the patches.
This is definitely a future work item. In this case, however, blk_desc should also be able to represent a partition.
- for the objects below, there is only one instance for each and so they are currently global data: efi_gop_obj, efi_net_obj,
efi_net_obj * is the handle of the network device. In future we should support multiple network devices.
It will be a natural extension.
simple_text_output_mode
- for loaded_image,
- link efi_loaded_image_obj to device's platdata
An EFI application can create an image out of "nothing". Just create a handle with InstallProtocolInterface() and then call LoadImage() with a pointer to some place in memory.
Many images loaded from the same device may be present at the same time, e.g. iPXE, GRUB, and Linux.
I don't get your point here, but please notice that a "loaded image" is more or less portion of main memory with loaded code. iPXE, GRUB and Linux are the same in this respect.
- Any efi protocol has a corresponding DM device.
Protocol implementations are not only provided by U-Boot but also by EFI applications and driver binaries. And of cause the EFI binaries will implement a lot of protocols completely unknown to U-Boot. So what should be the meaning of the above sentence in this context?
Can we instead add a uclass for each EFI protocol? Then U-Boot does know about them.
Yeah, I thought about defining an uclass for each EFI protocol. Given that a protocol defines a protocol-specific set of function interfaces in most cases, it will be natural to define a separate uclass.
On the other hand, this will make it a bit complicated to determine whether a given handle is an efi object or efi protocol in DM tree.
Regarding a protocol "unknown to U-Boot," it is kinda headache as we can invent a totally *original* protocol which is unknown at compile time of U-Boot. That is one of reasons why all the protocols have the same type of uclass in my current implementation. (I don't think there is any way to define uclass dynamically.)
Above you suggested that struct udevice * would be used as a handle. So on which handle is the protocol now installed in your model?
"efi_add_protocol" take a handle as a first argument, which is set to a parent of that protocol. If a handle is NULL here, a generated protocol handle will be temporarily attached to efi_root.
For a protocol like the device path protocol which is only a data structure with no related function modules I do not understand the benefit of creating a separate sub-device.
I think it is only a matter of convenience and to keep things regular.
Unifying device path hierarchy to DM tree is another challenge.
- link "struct efi_handler" to device's uclass_platdata
struct efi_handler is an item in the list of protocols installed on a handle. For some of the protocols installed by an EFI application there will not be any corresponding uclass.
As above, perhaps we should fix that?
As I said above, I recognize that this is an issue.
- be a child of a efi object (hence DM device) in DM device hierarchy so that enumerating protocols belonging to efi object is done by traversing the tree.
Above you said a struct udevice * would be a handle. So here you imply that for each protocol interface you will create an extra handle. That does not fit the EFI model.
Please don't interpret the concept to such an extent. While, say, a GPIO has a DM device (and efi handle in this sense), is it also an efi object? No.
- Any efi object which has a backing DM device should be created when that DM device is detected (and probed).
Detected or probed? This is not the same.
So what is your suggestion here?
- For efi_disk (or any object with EFI_BLOCK_IO_PROTOCOL),
- add UCLASS_PARTITION
- put partitions under a raw block device
- partitions as well as raw devices can be efi_disk
Agreed.
With those extensive changes, there still exists plenty of "wrapper" code. Do you have any idea to reduce it?
The concept presented does not cover:
- device, drivers, protocols created by EFI applications and driver binaries
I definitely want to see a good example so that I will investigate.
Can we create uclasses for each 'protocol'? Is there any reason why we cannot?
I think that I partly answered to you above.
- non-DM drivers and devices in U-Boot
This doesn't really matter as they will be gone soon. At the risk of repeating myself, EFI support should never have supported non-DM in the first place. It was not the right decision, in my view.
OK
It creates extra handles per installed protocol interface which should not exist in the EFI world.
So some rework of the concept is needed.
I suggest to start smaller:
- convert partitions to the DM model.
This is in later patches from what I can tell.
Yeah, to some extent. As I said above, blk_desc should be extended to support disk partitions on its own.
- provide a pointer serving as EFI handle in struct udevice
I actually feel that the approach here, while admittedly bold, seems to be a good step forward.
Regards, Simon
Best regards
Heinrich
Thank both of you for valuable comments.
-Takahiro Akashi
***** Example operation ****** (Two scsi disks, one with no partition, one with two partitions)
=> efi dev EFI: Initializing UCLASS_EFI_DRIVER Device Device Path ================ ==================== 000000007eef9470 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b) => scsi rescan
Reset SCSI scanning bus for devices... Target spinup took 0 ms. Target spinup took 0 ms. SATA link 2 timeout. SATA link 3 timeout. SATA link 4 timeout. SATA link 5 timeout. AHCI 0001.0000 32 slots 6 ports 1.5 Gbps 0x3f impl SATA mode flags: 64bit ncq only Device 0: (0:0) Vendor: ATA Prod.: QEMU HARDDISK Rev: 2.5+ Type: Hard Disk Capacity: 16.0 MB = 0.0 GB (32768 x 512) Device 0: (1:0) Vendor: ATA Prod.: QEMU HARDDISK Rev: 2.5+ Type: Hard Disk Capacity: 256.0 MB = 0.2 GB (524288 x 512) => efi dev Device Device Path ================ ==================== 000000007eef9470 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b) 000000007ef01c90 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(0,0) 000000007ef04910 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(1,0) 000000007ef04ee0 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(1,0)/HD(335544330,MBR,0x086246ba,0x17ff4f1a0,0x7eee3770) 000000007ef055a0 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(1,0)/HD(335544330,MBR,0x086246ba,0x17ff4f1a0,0x7eee3770) => dm tree Class index Probed Driver Name
root 0 [ + ] root_driver root_driver simple_bus 0 [ ] generic_simple_bus |-- platform@c000000 virtio 0 [ + ] virtio-mmio |-- virtio_mmio@a000000
[snip]
pci 0 [ + ] pci_generic_ecam |-- pcie@10000000 pci_generi 0 [ ] pci_generic_drv | |-- pci_0:0.0 virtio 32 [ ] virtio-pci.l | |-- virtio-pci.l#0 ahci 0 [ + ] ahci_pci | `-- ahci_pci scsi 0 [ + ] ahci_scsi | `-- ahci_scsi blk 0 [ + ] scsi_blk | |-- ahci_scsi.id0lun0 efi_protoc 8 [ + ] efi_disk | | |-- BLOCK_IO efi_protoc 9 [ + ] efi_device_path | | `-- Scsi(0,0) blk 1 [ + ] scsi_blk | `-- ahci_scsi.id1lun0 efi_protoc 10 [ + ] efi_disk | |-- BLOCK_IO efi_protoc 11 [ + ] efi_device_path | |-- Scsi(1,0) partition 0 [ + ] blk_partition | |-- ahci_scsi.id1lun0:1 efi_protoc 12 [ + ] efi_disk | | |-- BLOCK_IO efi_protoc 13 [ + ] efi_device_path | | |-- HD(335544330,MBR,0x086246ba,0x17ff4f1a0,0x7eee3770) efi_protoc 14 [ + ] efi_simple_file_syst | | `-- SIMPLE_FILE_SYSTEM partition 1 [ + ] blk_partition | `-- ahci_scsi.id1lun0:2 efi_protoc 15 [ + ] efi_disk | |-- BLOCK_IO efi_protoc 16 [ + ] efi_device_path | |-- HD(335544330,MBR,0x086246ba,0x17ff4f1a0,0x7eee3770) efi_protoc 17 [ + ] efi_simple_file_syst | `-- SIMPLE_FILE_SYSTEM rtc 0 [ ] rtc-pl031 |-- pl031@9010000 serial 0 [ ] serial_pl01x |-- pl011@9050000 serial 1 [ + ] serial_pl01x |-- pl011@9000000 efi_protoc 0 [ + ] efi_simple_text_outp | |-- SIMPLE_TEXT_OUTPUT efi_protoc 1 [ + ] efi_simple_text_inpu | |-- SIMPLE_TEXT_INPUT efi_protoc 2 [ + ] efi_simple_text_inpu | `-- SIMPLE_TEXT_INPUT_EX mtd 0 [ + ] cfi_flash |-- flash@0 firmware 0 [ + ] psci |-- psci sysreset 0 [ ] psci-sysreset | `-- psci-sysreset efi 0 [ + ] efi_root `-- UEFI sub system efi_protoc 3 [ + ] efi_device_path |-- VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b) efi_protoc 4 [ + ] efi_device_path_to_t |-- DEVICE_PATH_TO_TEXT efi_protoc 5 [ + ] efi_device_path_util |-- DEVICE_PATH_UTILITIES efi_protoc 6 [ + ] efi_unicode_collatio |-- en efi_driver 0 [ + ] EFI block driver `-- EFI block driver efi_protoc 7 [ + ] efi_driver_binding `-- DRIVER_BINDING
Thanks, -Takahiro Akashi
AKASHI Takahiro (15): efi_loader: efi objects and protocols as DM devices efi_loader: boottime: convert efi_loaded_image_obj to DM efi_loader: image_loader: aligned with DM efi_driver: rename UCLASS_EFI to UCLASS_EFI_DRIVER efi_loader: convert efi_root_node to DM efi_loader: device path: convert efi_device_path to DM efi_loader: unicode_collation: converted to DM efi_loader: console: convert efi console input/output to DM efi_loader: net: convert efi_net_obj to DM efi_loader: gop: convert efi_gop_obj to DM dm: blk: add UCLASS_PARTITION efi_loader: disk: convert efi_disk_obj to DM drivers: align block device drivers with DM-efi integration efi_driver: converted to DM cmd: efidebug: aligned with DM-efi integration
cmd/bootefi.c | 61 +-- cmd/efidebug.c | 5 +- common/usb_storage.c | 27 +- drivers/block/blk-uclass.c | 61 +++ drivers/scsi/scsi.c | 22 + drivers/serial/serial-uclass.c | 6 + drivers/video/video-uclass.c | 9 + include/blk.h | 24 + include/dm/device.h | 3 + include/dm/uclass-id.h | 6 +- include/efi.h | 4 +- include/efi_loader.h | 50 +- lib/efi_driver/efi_block_device.c | 36 +- lib/efi_driver/efi_uclass.c | 37 +- lib/efi_loader/efi_boottime.c | 605 ++++++++++++++------- lib/efi_loader/efi_console.c | 64 ++- lib/efi_loader/efi_device_path.c | 136 +++-- lib/efi_loader/efi_device_path_to_text.c | 55 ++ lib/efi_loader/efi_device_path_utilities.c | 14 + lib/efi_loader/efi_disk.c | 216 +++++--- lib/efi_loader/efi_file.c | 14 + lib/efi_loader/efi_gop.c | 28 +- lib/efi_loader/efi_image_loader.c | 61 ++- lib/efi_loader/efi_net.c | 50 +- lib/efi_loader/efi_root_node.c | 14 +- lib/efi_loader/efi_setup.c | 60 +- lib/efi_loader/efi_unicode_collation.c | 19 + net/eth-uclass.c | 5 + 28 files changed, 1226 insertions(+), 466 deletions(-)

On 2/12/19 8:24 AM, AKASHI Takahiro wrote:
Hi Heinrich, Simon,
On Sat, Feb 09, 2019 at 05:00:33PM -0600, Simon Glass wrote:
Hi Heinrich,
On Fri, 8 Feb 2019 at 03:36, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 2/8/19 9:15 AM, AKASHI Takahiro wrote:
# bootefi doesn't work with this patch set yet
This patch set came from the past discussion[1] on my "removable device support" patch and is intended to be an attempt to integrate efi objects into u-boot's Driver Model as much seamlessly as possible.
[1] https://lists.denx.de/pipermail/u-boot/2019-January/354010.html
Since this patch is a prototype (or POC, Proof-Of-Concept), the aim here is to discuss further about how in a better shape we will be able to merge the two worlds.
After RFC, Simon suggested that efi protocols could be also presented as DM devices. This is a major change in RFC v2.
Hello Takahiro,
thanks a lot for laying out your thoughts about a possible integration of the EFI subsystem and the driver model. Thanks also for providing a first implementation.
Yes indeed. It is very clever what you have been able to do Takahiro.
I think that I'm going to extremes here :)
The other extreme is what EDK2 does. They live with an EFI only model.
I think moving the DM model in this direction would be feasible and would be much more consistent than trying to map EFI objects onto DM structures with different semantics. But I do not see the man power to do such a change.
Between the two extremes is:
- link the worlds via pointers - move protocol implementations into the respective uclasses - endow these uclasses with an implementation of the driver binding protocol
This is feasible with the available capacity and sufficient to cover your use case of plugable devices.
I wonder what the EFI world will look like if all the handles and protocols are also DM devices. I don't expect that my patch will be upstreamed any time soon (or possibly forever not) So, instead of claiming the change would be meaningless, I'd welcome any suggestions, like what will happen if we merge/integrate EFI's A with U-Boot's B?
I'm willing to make best efforts to give such an idea a reality if possible. Then choices come after that.
Basic idea is
- efi_root is a DM device
- Any efi object, refered to by efi_handle_t in UEFI world, has a corresponding DM device.
EFI applications and drivers will create handles having no relation to the U-Boot world.
I suggest that we change that, i.e. that all devices in existence have a struct udevice. That way DM knows about everything and we don't have the strange parallel 'EFI' world. I don't see any need for it.
Simply, it would be nice that we can list all the applications and drivers loaded at one place, akin to linux's
- ls /proc/
- cat /proc/modules
(From the viewpoint of API, we can do that just by calling locate_handle(BY_PROTOCOL, EFI_LOADED_IMAGE, ...) though.)
- define efi_handle_t as "struct udevice *"
An EFI handle does not necessarily relate to any U-Boot device. Why should a handle which has not backing device carry the extra fields of struct udevice?
Because this is the U-Boot driver model. We should not have an EFI parallel to DM and certainly not just to save a few dozen bytes of data space. If you were trying to save data space, you would not use EFI :-)
Ah, thank you.
From a viewpoint of implementation, the situation where some handles
are DM devices and some are not could make the efi code, particularly boottime.c, quite ugly and complicated.
- for efi_disk,
- add "struct efi_disk_obj" to blk_desc
struct efi_disk_obj * is currently the handle of the block device. So you only some fields may be moved to blk_desc. But I guess I will find that in one of the patches.
This is definitely a future work item. In this case, however, blk_desc should also be able to represent a partition.
- for the objects below, there is only one instance for each and so they are currently global data: efi_gop_obj, efi_net_obj,
efi_net_obj * is the handle of the network device. In future we should support multiple network devices.
It will be a natural extension.
simple_text_output_mode
- for loaded_image,
- link efi_loaded_image_obj to device's platdata
An EFI application can create an image out of "nothing". Just create a handle with InstallProtocolInterface() and then call LoadImage() with a pointer to some place in memory.
Many images loaded from the same device may be present at the same time, e.g. iPXE, GRUB, and Linux.
I don't get your point here, but please notice that a "loaded image" is more or less portion of main memory with loaded code. iPXE, GRUB and Linux are the same in this respect.
Why do you want to treat such a memory area as a separate device?
- Any efi protocol has a corresponding DM device.
Protocol implementations are not only provided by U-Boot but also by EFI applications and driver binaries. And of cause the EFI binaries will implement a lot of protocols completely unknown to U-Boot. So what should be the meaning of the above sentence in this context?
Can we instead add a uclass for each EFI protocol? Then U-Boot does know about them.
Yeah, I thought about defining an uclass for each EFI protocol. Given that a protocol defines a protocol-specific set of function interfaces in most cases, it will be natural to define a separate uclass.
An EFI binary can implement any EFI protocol that only exists for this special application. E.g. somebody could write an EFI driver implementing NVME over TCP.
Requiring that U-Boot has a uclass for every protocol would mean that at U-Boot compile time you would already have to define which EFI binaries a user is able to load. E.g. if a uclass for NVME over TCP does not exist a user would not be able to run above hypothetical binary.
On the other hand, this will make it a bit complicated to determine whether a given handle is an efi object or efi protocol in DM tree.
In EFI terminology a protocol is not a handle but an abstract interface. The implementation of a protocol is called protocol interface.
A protocol interface may be installed on one or more handles. But it should not be enumerated by LocateHandles(SearchType = AllHandles)
Regarding a protocol "unknown to U-Boot," it is kinda headache as we can invent a totally *original* protocol which is unknown at compile time of U-Boot. That is one of reasons why all the protocols have the same type of uclass in my current implementation. (I don't think there is any way to define uclass dynamically.)
What is the benefit of protocol interface pointing to a uclass that doesn't implement the protocol?
Above you suggested that struct udevice * would be used as a handle. So on which handle is the protocol now installed in your model?
"efi_add_protocol" take a handle as a first argument, which is set to a parent of that protocol. If a handle is NULL here, a generated protocol handle will be temporarily attached to efi_root.
For a protocol like the device path protocol which is only a data structure with no related function modules I do not understand the benefit of creating a separate sub-device.
I think it is only a matter of convenience and to keep things regular.
Unifying device path hierarchy to DM tree is another challenge.
As an application may change the device path protocol of a handle at any time and we do not want to mess up the DM tree I would not see that this is possible.
- link "struct efi_handler" to device's uclass_platdata
struct efi_handler is an item in the list of protocols installed on a handle. For some of the protocols installed by an EFI application there will not be any corresponding uclass.
As above, perhaps we should fix that?
As I said above, I recognize that this is an issue.
- be a child of a efi object (hence DM device) in DM device hierarchy so that enumerating protocols belonging to efi object is done by traversing the tree.
Above you said a struct udevice * would be a handle. So here you imply that for each protocol interface you will create an extra handle. That does not fit the EFI model.
Please don't interpret the concept to such an extent. While, say, a GPIO has a DM device (and efi handle in this sense), is it also an efi object? No.
- Any efi object which has a backing DM device should be created when that DM device is detected (and probed).
Detected or probed? This is not the same.
So what is your suggestion here?
U-Boot follows the idea of late probing. So I guess we want an EFI handle to be created when the DM device is detected and probe it when the installed protocol is used for the first time.
- For efi_disk (or any object with EFI_BLOCK_IO_PROTOCOL),
- add UCLASS_PARTITION
- put partitions under a raw block device
- partitions as well as raw devices can be efi_disk
Agreed.
With those extensive changes, there still exists plenty of "wrapper" code. Do you have any idea to reduce it?
The concept presented does not cover:
- device, drivers, protocols created by EFI applications and driver binaries
I definitely want to see a good example so that I will investigate.
Can we create uclasses for each 'protocol'? Is there any reason why we cannot?
I think that I partly answered to you above.
- non-DM drivers and devices in U-Boot
This doesn't really matter as they will be gone soon. At the risk of repeating myself, EFI support should never have supported non-DM in the first place. It was not the right decision, in my view.
OK
It creates extra handles per installed protocol interface which should not exist in the EFI world.
So some rework of the concept is needed.
I suggest to start smaller:
- convert partitions to the DM model.
This is in later patches from what I can tell.
I would put it at the beginning as it is required for your use case of plugable devices.
Best regards
Heinrich
Yeah, to some extent. As I said above, blk_desc should be extended to support disk partitions on its own.
- provide a pointer serving as EFI handle in struct udevice
I actually feel that the approach here, while admittedly bold, seems to be a good step forward.
Regards, Simon
Best regards
Heinrich
Thank both of you for valuable comments.
-Takahiro Akashi
***** Example operation ****** (Two scsi disks, one with no partition, one with two partitions)
=> efi dev EFI: Initializing UCLASS_EFI_DRIVER Device Device Path ================ ==================== 000000007eef9470 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b) => scsi rescan
Reset SCSI scanning bus for devices... Target spinup took 0 ms. Target spinup took 0 ms. SATA link 2 timeout. SATA link 3 timeout. SATA link 4 timeout. SATA link 5 timeout. AHCI 0001.0000 32 slots 6 ports 1.5 Gbps 0x3f impl SATA mode flags: 64bit ncq only Device 0: (0:0) Vendor: ATA Prod.: QEMU HARDDISK Rev: 2.5+ Type: Hard Disk Capacity: 16.0 MB = 0.0 GB (32768 x 512) Device 0: (1:0) Vendor: ATA Prod.: QEMU HARDDISK Rev: 2.5+ Type: Hard Disk Capacity: 256.0 MB = 0.2 GB (524288 x 512) => efi dev Device Device Path ================ ==================== 000000007eef9470 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b) 000000007ef01c90 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(0,0) 000000007ef04910 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(1,0) 000000007ef04ee0 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(1,0)/HD(335544330,MBR,0x086246ba,0x17ff4f1a0,0x7eee3770) 000000007ef055a0 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(1,0)/HD(335544330,MBR,0x086246ba,0x17ff4f1a0,0x7eee3770) => dm tree Class index Probed Driver Name
root 0 [ + ] root_driver root_driver simple_bus 0 [ ] generic_simple_bus |-- platform@c000000 virtio 0 [ + ] virtio-mmio |-- virtio_mmio@a000000
[snip]
pci 0 [ + ] pci_generic_ecam |-- pcie@10000000 pci_generi 0 [ ] pci_generic_drv | |-- pci_0:0.0 virtio 32 [ ] virtio-pci.l | |-- virtio-pci.l#0 ahci 0 [ + ] ahci_pci | `-- ahci_pci scsi 0 [ + ] ahci_scsi | `-- ahci_scsi blk 0 [ + ] scsi_blk | |-- ahci_scsi.id0lun0 efi_protoc 8 [ + ] efi_disk | | |-- BLOCK_IO efi_protoc 9 [ + ] efi_device_path | | `-- Scsi(0,0) blk 1 [ + ] scsi_blk | `-- ahci_scsi.id1lun0 efi_protoc 10 [ + ] efi_disk | |-- BLOCK_IO efi_protoc 11 [ + ] efi_device_path | |-- Scsi(1,0) partition 0 [ + ] blk_partition | |-- ahci_scsi.id1lun0:1 efi_protoc 12 [ + ] efi_disk | | |-- BLOCK_IO efi_protoc 13 [ + ] efi_device_path | | |-- HD(335544330,MBR,0x086246ba,0x17ff4f1a0,0x7eee3770) efi_protoc 14 [ + ] efi_simple_file_syst | | `-- SIMPLE_FILE_SYSTEM partition 1 [ + ] blk_partition | `-- ahci_scsi.id1lun0:2 efi_protoc 15 [ + ] efi_disk | |-- BLOCK_IO efi_protoc 16 [ + ] efi_device_path | |-- HD(335544330,MBR,0x086246ba,0x17ff4f1a0,0x7eee3770) efi_protoc 17 [ + ] efi_simple_file_syst | `-- SIMPLE_FILE_SYSTEM rtc 0 [ ] rtc-pl031 |-- pl031@9010000 serial 0 [ ] serial_pl01x |-- pl011@9050000 serial 1 [ + ] serial_pl01x |-- pl011@9000000 efi_protoc 0 [ + ] efi_simple_text_outp | |-- SIMPLE_TEXT_OUTPUT efi_protoc 1 [ + ] efi_simple_text_inpu | |-- SIMPLE_TEXT_INPUT efi_protoc 2 [ + ] efi_simple_text_inpu | `-- SIMPLE_TEXT_INPUT_EX mtd 0 [ + ] cfi_flash |-- flash@0 firmware 0 [ + ] psci |-- psci sysreset 0 [ ] psci-sysreset | `-- psci-sysreset efi 0 [ + ] efi_root `-- UEFI sub system efi_protoc 3 [ + ] efi_device_path |-- VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b) efi_protoc 4 [ + ] efi_device_path_to_t |-- DEVICE_PATH_TO_TEXT efi_protoc 5 [ + ] efi_device_path_util |-- DEVICE_PATH_UTILITIES efi_protoc 6 [ + ] efi_unicode_collatio |-- en efi_driver 0 [ + ] EFI block driver `-- EFI block driver efi_protoc 7 [ + ] efi_driver_binding `-- DRIVER_BINDING
Thanks, -Takahiro Akashi
AKASHI Takahiro (15): efi_loader: efi objects and protocols as DM devices efi_loader: boottime: convert efi_loaded_image_obj to DM efi_loader: image_loader: aligned with DM efi_driver: rename UCLASS_EFI to UCLASS_EFI_DRIVER efi_loader: convert efi_root_node to DM efi_loader: device path: convert efi_device_path to DM efi_loader: unicode_collation: converted to DM efi_loader: console: convert efi console input/output to DM efi_loader: net: convert efi_net_obj to DM efi_loader: gop: convert efi_gop_obj to DM dm: blk: add UCLASS_PARTITION efi_loader: disk: convert efi_disk_obj to DM drivers: align block device drivers with DM-efi integration efi_driver: converted to DM cmd: efidebug: aligned with DM-efi integration
cmd/bootefi.c | 61 +-- cmd/efidebug.c | 5 +- common/usb_storage.c | 27 +- drivers/block/blk-uclass.c | 61 +++ drivers/scsi/scsi.c | 22 + drivers/serial/serial-uclass.c | 6 + drivers/video/video-uclass.c | 9 + include/blk.h | 24 + include/dm/device.h | 3 + include/dm/uclass-id.h | 6 +- include/efi.h | 4 +- include/efi_loader.h | 50 +- lib/efi_driver/efi_block_device.c | 36 +- lib/efi_driver/efi_uclass.c | 37 +- lib/efi_loader/efi_boottime.c | 605 ++++++++++++++------- lib/efi_loader/efi_console.c | 64 ++- lib/efi_loader/efi_device_path.c | 136 +++-- lib/efi_loader/efi_device_path_to_text.c | 55 ++ lib/efi_loader/efi_device_path_utilities.c | 14 + lib/efi_loader/efi_disk.c | 216 +++++--- lib/efi_loader/efi_file.c | 14 + lib/efi_loader/efi_gop.c | 28 +- lib/efi_loader/efi_image_loader.c | 61 ++- lib/efi_loader/efi_net.c | 50 +- lib/efi_loader/efi_root_node.c | 14 +- lib/efi_loader/efi_setup.c | 60 +- lib/efi_loader/efi_unicode_collation.c | 19 + net/eth-uclass.c | 5 + 28 files changed, 1226 insertions(+), 466 deletions(-)

Hi Heinrich,
On Tue, 12 Feb 2019 at 17:53, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 2/12/19 8:24 AM, AKASHI Takahiro wrote:
Hi Heinrich, Simon,
On Sat, Feb 09, 2019 at 05:00:33PM -0600, Simon Glass wrote:
Hi Heinrich,
On Fri, 8 Feb 2019 at 03:36, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 2/8/19 9:15 AM, AKASHI Takahiro wrote:
# bootefi doesn't work with this patch set yet
This patch set came from the past discussion[1] on my "removable device support" patch and is intended to be an attempt to integrate efi objects into u-boot's Driver Model as much seamlessly as possible.
[1] https://lists.denx.de/pipermail/u-boot/2019-January/354010.html
Since this patch is a prototype (or POC, Proof-Of-Concept), the aim here is to discuss further about how in a better shape we will be able to merge the two worlds.
After RFC, Simon suggested that efi protocols could be also presented as DM devices. This is a major change in RFC v2.
Hello Takahiro,
thanks a lot for laying out your thoughts about a possible integration of the EFI subsystem and the driver model. Thanks also for providing a first implementation.
Yes indeed. It is very clever what you have been able to do Takahiro.
I think that I'm going to extremes here :)
The other extreme is what EDK2 does. They live with an EFI only model.
I think moving the DM model in this direction would be feasible and would be much more consistent than trying to map EFI objects onto DM structures with different semantics. But I do not see the man power to do such a change.
I think you might be describing some other bootloader :-) I think it's fine to add EFI support to U-Boot but I don't like the idea of moving the internal structure to that. Overall I find EFI confusing and overly complicated.
Between the two extremes is:
- link the worlds via pointers
- move protocol implementations into the respective uclasses
- endow these uclasses with an implementation of the driver binding protocol
This is feasible with the available capacity and sufficient to cover your use case of plugable devices.
That sounds good.
I wonder what the EFI world will look like if all the handles and protocols are also DM devices. I don't expect that my patch will be upstreamed any time soon (or possibly forever not) So, instead of claiming the change would be meaningless, I'd welcome any suggestions, like what will happen if we merge/integrate EFI's A with U-Boot's B?
I'm willing to make best efforts to give such an idea a reality if possible. Then choices come after that.
Basic idea is
- efi_root is a DM device
- Any efi object, refered to by efi_handle_t in UEFI world, has a corresponding DM device.
EFI applications and drivers will create handles having no relation to the U-Boot world.
I suggest that we change that, i.e. that all devices in existence have a struct udevice. That way DM knows about everything and we don't have the strange parallel 'EFI' world. I don't see any need for it.
Simply, it would be nice that we can list all the applications and drivers loaded at one place, akin to linux's
- ls /proc/
- cat /proc/modules
(From the viewpoint of API, we can do that just by calling locate_handle(BY_PROTOCOL, EFI_LOADED_IMAGE, ...) though.)
- define efi_handle_t as "struct udevice *"
An EFI handle does not necessarily relate to any U-Boot device. Why should a handle which has not backing device carry the extra fields of struct udevice?
Because this is the U-Boot driver model. We should not have an EFI parallel to DM and certainly not just to save a few dozen bytes of data space. If you were trying to save data space, you would not use EFI :-)
Ah, thank you.
From a viewpoint of implementation, the situation where some handles
are DM devices and some are not could make the efi code, particularly boottime.c, quite ugly and complicated.
- for efi_disk,
- add "struct efi_disk_obj" to blk_desc
struct efi_disk_obj * is currently the handle of the block device. So you only some fields may be moved to blk_desc. But I guess I will find that in one of the patches.
This is definitely a future work item. In this case, however, blk_desc should also be able to represent a partition.
- for the objects below, there is only one instance for each and so they are currently global data: efi_gop_obj, efi_net_obj,
efi_net_obj * is the handle of the network device. In future we should support multiple network devices.
It will be a natural extension.
simple_text_output_mode
- for loaded_image,
- link efi_loaded_image_obj to device's platdata
An EFI application can create an image out of "nothing". Just create a handle with InstallProtocolInterface() and then call LoadImage() with a pointer to some place in memory.
Many images loaded from the same device may be present at the same time, e.g. iPXE, GRUB, and Linux.
I don't get your point here, but please notice that a "loaded image" is more or less portion of main memory with loaded code. iPXE, GRUB and Linux are the same in this respect.
Why do you want to treat such a memory area as a separate device?
- Any efi protocol has a corresponding DM device.
Protocol implementations are not only provided by U-Boot but also by EFI applications and driver binaries. And of cause the EFI binaries will implement a lot of protocols completely unknown to U-Boot. So what should be the meaning of the above sentence in this context?
Can we instead add a uclass for each EFI protocol? Then U-Boot does know about them.
Yeah, I thought about defining an uclass for each EFI protocol. Given that a protocol defines a protocol-specific set of function interfaces in most cases, it will be natural to define a separate uclass.
An EFI binary can implement any EFI protocol that only exists for this special application. E.g. somebody could write an EFI driver implementing NVME over TCP.
Requiring that U-Boot has a uclass for every protocol would mean that at U-Boot compile time you would already have to define which EFI binaries a user is able to load. E.g. if a uclass for NVME over TCP does not exist a user would not be able to run above hypothetical binary.
Yes that's right, but I think that makes sense to have that support in U-Boot itself rather than out on a limb with EFI. It is natural consequence of fully using DM for EFI.
On the other hand, this will make it a bit complicated to determine whether a given handle is an efi object or efi protocol in DM tree.
In EFI terminology a protocol is not a handle but an abstract interface. The implementation of a protocol is called protocol interface.
A protocol interface may be installed on one or more handles. But it should not be enumerated by LocateHandles(SearchType = AllHandles)
I need to make time to read the EFI spec another 5 times :-) As I understand it the protocol corresponds to the operations in a U-Boot uclass.
Regarding a protocol "unknown to U-Boot," it is kinda headache as we can invent a totally *original* protocol which is unknown at compile time of U-Boot. That is one of reasons why all the protocols have the same type of uclass in my current implementation. (I don't think there is any way to define uclass dynamically.)
What is the benefit of protocol interface pointing to a uclass that doesn't implement the protocol?
I don't know about that, it doesn't seem useful.
Above you suggested that struct udevice * would be used as a handle. So on which handle is the protocol now installed in your model?
"efi_add_protocol" take a handle as a first argument, which is set to a parent of that protocol. If a handle is NULL here, a generated protocol handle will be temporarily attached to efi_root.
For a protocol like the device path protocol which is only a data structure with no related function modules I do not understand the benefit of creating a separate sub-device.
I think it is only a matter of convenience and to keep things regular.
Unifying device path hierarchy to DM tree is another challenge.
As an application may change the device path protocol of a handle at any time and we do not want to mess up the DM tree I would not see that this is possible.
What is the use case to changing the device path protocol?
- link "struct efi_handler" to device's uclass_platdata
struct efi_handler is an item in the list of protocols installed on a handle. For some of the protocols installed by an EFI application there will not be any corresponding uclass.
As above, perhaps we should fix that?
As I said above, I recognize that this is an issue.
- be a child of a efi object (hence DM device) in DM device hierarchy so that enumerating protocols belonging to efi object is done by traversing the tree.
Above you said a struct udevice * would be a handle. So here you imply that for each protocol interface you will create an extra handle. That does not fit the EFI model.
Please don't interpret the concept to such an extent. While, say, a GPIO has a DM device (and efi handle in this sense), is it also an efi object? No.
- Any efi object which has a backing DM device should be created when that DM device is detected (and probed).
Detected or probed? This is not the same.
So what is your suggestion here?
U-Boot follows the idea of late probing. So I guess we want an EFI handle to be created when the DM device is detected and probe it when the installed protocol is used for the first time.
That sound right to me.
- For efi_disk (or any object with EFI_BLOCK_IO_PROTOCOL),
- add UCLASS_PARTITION
- put partitions under a raw block device
- partitions as well as raw devices can be efi_disk
Agreed.
With those extensive changes, there still exists plenty of "wrapper" code. Do you have any idea to reduce it?
The concept presented does not cover:
- device, drivers, protocols created by EFI applications and driver binaries
I definitely want to see a good example so that I will investigate.
Can we create uclasses for each 'protocol'? Is there any reason why we cannot?
I think that I partly answered to you above.
- non-DM drivers and devices in U-Boot
This doesn't really matter as they will be gone soon. At the risk of repeating myself, EFI support should never have supported non-DM in the first place. It was not the right decision, in my view.
OK
It creates extra handles per installed protocol interface which should not exist in the EFI world.
So some rework of the concept is needed.
I suggest to start smaller:
- convert partitions to the DM model.
This is in later patches from what I can tell.
I would put it at the beginning as it is required for your use case of plugable devices.
Regards, Simon
Best regards
Heinrich
Yeah, to some extent. As I said above, blk_desc should be extended to support disk partitions on its own.
- provide a pointer serving as EFI handle in struct udevice
I actually feel that the approach here, while admittedly bold, seems to be a good step forward.
Regards, Simon
Best regards
Heinrich
Thank both of you for valuable comments.
-Takahiro Akashi
***** Example operation ****** (Two scsi disks, one with no partition, one with two partitions)
=> efi dev EFI: Initializing UCLASS_EFI_DRIVER Device Device Path ================ ==================== 000000007eef9470 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b) => scsi rescan
Reset SCSI scanning bus for devices... Target spinup took 0 ms. Target spinup took 0 ms. SATA link 2 timeout. SATA link 3 timeout. SATA link 4 timeout. SATA link 5 timeout. AHCI 0001.0000 32 slots 6 ports 1.5 Gbps 0x3f impl SATA mode flags: 64bit ncq only Device 0: (0:0) Vendor: ATA Prod.: QEMU HARDDISK Rev: 2.5+ Type: Hard Disk Capacity: 16.0 MB = 0.0 GB (32768 x 512) Device 0: (1:0) Vendor: ATA Prod.: QEMU HARDDISK Rev: 2.5+ Type: Hard Disk Capacity: 256.0 MB = 0.2 GB (524288 x 512) => efi dev Device Device Path ================ ==================== 000000007eef9470 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b) 000000007ef01c90 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(0,0) 000000007ef04910 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(1,0) 000000007ef04ee0 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(1,0)/HD(335544330,MBR,0x086246ba,0x17ff4f1a0,0x7eee3770) 000000007ef055a0 /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(1,0)/HD(335544330,MBR,0x086246ba,0x17ff4f1a0,0x7eee3770) => dm tree Class index Probed Driver Name
root 0 [ + ] root_driver root_driver simple_bus 0 [ ] generic_simple_bus |-- platform@c000000 virtio 0 [ + ] virtio-mmio |-- virtio_mmio@a000000
[snip]
pci 0 [ + ] pci_generic_ecam |-- pcie@10000000 pci_generi 0 [ ] pci_generic_drv | |-- pci_0:0.0 virtio 32 [ ] virtio-pci.l | |-- virtio-pci.l#0 ahci 0 [ + ] ahci_pci | `-- ahci_pci scsi 0 [ + ] ahci_scsi | `-- ahci_scsi blk 0 [ + ] scsi_blk | |-- ahci_scsi.id0lun0 efi_protoc 8 [ + ] efi_disk | | |-- BLOCK_IO efi_protoc 9 [ + ] efi_device_path | | `-- Scsi(0,0) blk 1 [ + ] scsi_blk | `-- ahci_scsi.id1lun0 efi_protoc 10 [ + ] efi_disk | |-- BLOCK_IO efi_protoc 11 [ + ] efi_device_path | |-- Scsi(1,0) partition 0 [ + ] blk_partition | |-- ahci_scsi.id1lun0:1 efi_protoc 12 [ + ] efi_disk | | |-- BLOCK_IO efi_protoc 13 [ + ] efi_device_path | | |-- HD(335544330,MBR,0x086246ba,0x17ff4f1a0,0x7eee3770) efi_protoc 14 [ + ] efi_simple_file_syst | | `-- SIMPLE_FILE_SYSTEM partition 1 [ + ] blk_partition | `-- ahci_scsi.id1lun0:2 efi_protoc 15 [ + ] efi_disk | |-- BLOCK_IO efi_protoc 16 [ + ] efi_device_path | |-- HD(335544330,MBR,0x086246ba,0x17ff4f1a0,0x7eee3770) efi_protoc 17 [ + ] efi_simple_file_syst | `-- SIMPLE_FILE_SYSTEM rtc 0 [ ] rtc-pl031 |-- pl031@9010000 serial 0 [ ] serial_pl01x |-- pl011@9050000 serial 1 [ + ] serial_pl01x |-- pl011@9000000 efi_protoc 0 [ + ] efi_simple_text_outp | |-- SIMPLE_TEXT_OUTPUT efi_protoc 1 [ + ] efi_simple_text_inpu | |-- SIMPLE_TEXT_INPUT efi_protoc 2 [ + ] efi_simple_text_inpu | `-- SIMPLE_TEXT_INPUT_EX mtd 0 [ + ] cfi_flash |-- flash@0 firmware 0 [ + ] psci |-- psci sysreset 0 [ ] psci-sysreset | `-- psci-sysreset efi 0 [ + ] efi_root `-- UEFI sub system efi_protoc 3 [ + ] efi_device_path |-- VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b) efi_protoc 4 [ + ] efi_device_path_to_t |-- DEVICE_PATH_TO_TEXT efi_protoc 5 [ + ] efi_device_path_util |-- DEVICE_PATH_UTILITIES efi_protoc 6 [ + ] efi_unicode_collatio |-- en efi_driver 0 [ + ] EFI block driver `-- EFI block driver efi_protoc 7 [ + ] efi_driver_binding `-- DRIVER_BINDING
Thanks, -Takahiro Akashi
AKASHI Takahiro (15): efi_loader: efi objects and protocols as DM devices efi_loader: boottime: convert efi_loaded_image_obj to DM efi_loader: image_loader: aligned with DM efi_driver: rename UCLASS_EFI to UCLASS_EFI_DRIVER efi_loader: convert efi_root_node to DM efi_loader: device path: convert efi_device_path to DM efi_loader: unicode_collation: converted to DM efi_loader: console: convert efi console input/output to DM efi_loader: net: convert efi_net_obj to DM efi_loader: gop: convert efi_gop_obj to DM dm: blk: add UCLASS_PARTITION efi_loader: disk: convert efi_disk_obj to DM drivers: align block device drivers with DM-efi integration efi_driver: converted to DM cmd: efidebug: aligned with DM-efi integration
cmd/bootefi.c | 61 +-- cmd/efidebug.c | 5 +- common/usb_storage.c | 27 +- drivers/block/blk-uclass.c | 61 +++ drivers/scsi/scsi.c | 22 + drivers/serial/serial-uclass.c | 6 + drivers/video/video-uclass.c | 9 + include/blk.h | 24 + include/dm/device.h | 3 + include/dm/uclass-id.h | 6 +- include/efi.h | 4 +- include/efi_loader.h | 50 +- lib/efi_driver/efi_block_device.c | 36 +- lib/efi_driver/efi_uclass.c | 37 +- lib/efi_loader/efi_boottime.c | 605 ++++++++++++++------- lib/efi_loader/efi_console.c | 64 ++- lib/efi_loader/efi_device_path.c | 136 +++-- lib/efi_loader/efi_device_path_to_text.c | 55 ++ lib/efi_loader/efi_device_path_utilities.c | 14 + lib/efi_loader/efi_disk.c | 216 +++++--- lib/efi_loader/efi_file.c | 14 + lib/efi_loader/efi_gop.c | 28 +- lib/efi_loader/efi_image_loader.c | 61 ++- lib/efi_loader/efi_net.c | 50 +- lib/efi_loader/efi_root_node.c | 14 +- lib/efi_loader/efi_setup.c | 60 +- lib/efi_loader/efi_unicode_collation.c | 19 + net/eth-uclass.c | 5 + 28 files changed, 1226 insertions(+), 466 deletions(-)

Hi,
On Fri, 8 Feb 2019 at 01:14, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
# bootefi doesn't work with this patch set yet
This patch set came from the past discussion[1] on my "removable device support" patch and is intended to be an attempt to integrate efi objects into u-boot's Driver Model as much seamlessly as possible.
[1] https://lists.denx.de/pipermail/u-boot/2019-January/354010.html
Is this pushed to a tree somewhere? If not, what commit does this series apply on top of?
Regards, Simon

Simon,
On Sat, Feb 09, 2019 at 01:08:10PM -0700, Simon Glass wrote:
Hi,
On Fri, 8 Feb 2019 at 01:14, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
# bootefi doesn't work with this patch set yet
This patch set came from the past discussion[1] on my "removable device support" patch and is intended to be an attempt to integrate efi objects into u-boot's Driver Model as much seamlessly as possible.
[1] https://lists.denx.de/pipermail/u-boot/2019-January/354010.html
Is this pushed to a tree somewhere? If not, what commit does this series apply on top of?
Please take a look at: https://git.linaro.org/people/takahiro.akashi/u-boot.git/log/?h=efi/dm
I don't think we need any prerequisite patch although I added my own patches like efidebug.
Thanks, -Takahiro Akashi
Regards, Simon

Hi Takahiro,
On Fri, 8 Feb 2019 at 02:14, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
# bootefi doesn't work with this patch set yet
This patch set came from the past discussion[1] on my "removable device support" patch and is intended to be an attempt to integrate efi objects into u-boot's Driver Model as much seamlessly as possible.
[1] https://lists.denx.de/pipermail/u-boot/2019-January/354010.html
Some general comments:
protocol_list: Can you use DM_GET_DRIVER? It should be more efficient
efi_open_protocol_information: - rename of protocol to protocol_guid should be in a separate patch
u-boot - please use 'U-Boot' consistently
Your patch to rename UCLASS_EFI -> UCLASS_EFI_DRIVER still leaves UCLASS_EFI remaining. Can you mention why>
It says efi_root is for backward compatibility. Just temporary? I could not quite figure that out.
Use if (IS_ENABLED()) instead of #ifdef where you can.
I am very encouraged by this series as it genuinely unifies EFI with DM. Re your comment about wrapper code, I suspect that might become clearer once the data structures are unified.
Regards, Simon

On Sat, Feb 09, 2019 at 05:04:19PM -0600, Simon Glass wrote:
Hi Takahiro,
On Fri, 8 Feb 2019 at 02:14, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
# bootefi doesn't work with this patch set yet
This patch set came from the past discussion[1] on my "removable device support" patch and is intended to be an attempt to integrate efi objects into u-boot's Driver Model as much seamlessly as possible.
[1] https://lists.denx.de/pipermail/u-boot/2019-January/354010.html
Some general comments:
protocol_list: Can you use DM_GET_DRIVER? It should be more efficient
Okay.
efi_open_protocol_information:
- rename of protocol to protocol_guid should be in a separate patch
Okay, but I may will rename other argument names instead.
u-boot - please use 'U-Boot' consistently
Sure.
Your patch to rename UCLASS_EFI -> UCLASS_EFI_DRIVER still leaves UCLASS_EFI remaining. Can you mention why>
It says efi_root is for backward compatibility. Just temporary? I could not quite figure that out.
The concept of "efi_root" is a discussion.
Use if (IS_ENABLED()) instead of #ifdef where you can.
Okay
I am very encouraged by this series as it genuinely unifies EFI with DM. Re your comment about wrapper code, I suspect that might become clearer once the data structures are unified.
Your comments also encourage me very much.
Thanks! -Takahiro Akashi
Regards, Simon
participants (3)
-
AKASHI Takahiro
-
Heinrich Schuchardt
-
Simon Glass