All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM
@ 2019-02-08  8:15 AKASHI Takahiro
  2019-02-08  8:15 ` [U-Boot] [RFC v2 01/15] efi_loader: efi objects and protocols as DM devices AKASHI Takahiro
                   ` (17 more replies)
  0 siblings, 18 replies; 31+ messages in thread
From: AKASHI Takahiro @ 2019-02-08  8:15 UTC (permalink / raw)
  To: u-boot

# 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 at c000000
 virtio      0  [ + ]   virtio-mmio           |-- virtio_mmio at a000000

 [snip]

 pci         0  [ + ]   pci_generic_ecam      |-- pcie at 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 at 9010000
 serial      0  [   ]   serial_pl01x          |-- pl011 at 9050000
 serial      1  [ + ]   serial_pl01x          |-- pl011 at 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 at 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(-)

-- 
2.19.1

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 01/15] efi_loader: efi objects and protocols as DM devices
  2019-02-08  8:15 [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM AKASHI Takahiro
@ 2019-02-08  8:15 ` AKASHI Takahiro
  2019-02-08 17:47   ` Heinrich Schuchardt
  2019-02-08  8:15 ` [U-Boot] [RFC v2 02/15] efi_loader: boottime: convert efi_loaded_image_obj to DM AKASHI Takahiro
                   ` (16 subsequent siblings)
  17 siblings, 1 reply; 31+ messages in thread
From: AKASHI Takahiro @ 2019-02-08  8:15 UTC (permalink / raw)
  To: u-boot

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),
+};
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 02/15] efi_loader: boottime: convert efi_loaded_image_obj to DM
  2019-02-08  8:15 [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM AKASHI Takahiro
  2019-02-08  8:15 ` [U-Boot] [RFC v2 01/15] efi_loader: efi objects and protocols as DM devices AKASHI Takahiro
@ 2019-02-08  8:15 ` AKASHI Takahiro
  2019-02-08 17:53   ` Heinrich Schuchardt
  2019-02-08  8:15 ` [U-Boot] [RFC v2 03/15] efi_loader: image_loader: aligned with DM AKASHI Takahiro
                   ` (15 subsequent siblings)
  17 siblings, 1 reply; 31+ messages in thread
From: AKASHI Takahiro @ 2019-02-08  8:15 UTC (permalink / raw)
  To: u-boot

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,
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 03/15] efi_loader: image_loader: aligned with DM
  2019-02-08  8:15 [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM AKASHI Takahiro
  2019-02-08  8:15 ` [U-Boot] [RFC v2 01/15] efi_loader: efi objects and protocols as DM devices AKASHI Takahiro
  2019-02-08  8:15 ` [U-Boot] [RFC v2 02/15] efi_loader: boottime: convert efi_loaded_image_obj to DM AKASHI Takahiro
@ 2019-02-08  8:15 ` AKASHI Takahiro
  2019-02-08  8:15 ` [U-Boot] [RFC v2 04/15] efi_driver: rename UCLASS_EFI to UCLASS_EFI_DRIVER AKASHI Takahiro
                   ` (14 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: AKASHI Takahiro @ 2019-02-08  8:15 UTC (permalink / raw)
  To: u-boot

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;
 }
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 04/15] efi_driver: rename UCLASS_EFI to UCLASS_EFI_DRIVER
  2019-02-08  8:15 [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM AKASHI Takahiro
                   ` (2 preceding siblings ...)
  2019-02-08  8:15 ` [U-Boot] [RFC v2 03/15] efi_loader: image_loader: aligned with DM AKASHI Takahiro
@ 2019-02-08  8:15 ` AKASHI Takahiro
  2019-02-08  8:15 ` [U-Boot] [RFC v2 05/15] efi_loader: convert efi_root_node to DM AKASHI Takahiro
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: AKASHI Takahiro @ 2019-02-08  8:15 UTC (permalink / raw)
  To: u-boot

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,
 };
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 05/15] efi_loader: convert efi_root_node to DM
  2019-02-08  8:15 [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM AKASHI Takahiro
                   ` (3 preceding siblings ...)
  2019-02-08  8:15 ` [U-Boot] [RFC v2 04/15] efi_driver: rename UCLASS_EFI to UCLASS_EFI_DRIVER AKASHI Takahiro
@ 2019-02-08  8:15 ` AKASHI Takahiro
  2019-02-08  8:15 ` [U-Boot] [RFC v2 06/15] efi_loader: device path: convert efi_device_path " AKASHI Takahiro
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: AKASHI Takahiro @ 2019-02-08  8:15 UTC (permalink / raw)
  To: u-boot

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,
+};
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 06/15] efi_loader: device path: convert efi_device_path to DM
  2019-02-08  8:15 [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM AKASHI Takahiro
                   ` (4 preceding siblings ...)
  2019-02-08  8:15 ` [U-Boot] [RFC v2 05/15] efi_loader: convert efi_root_node to DM AKASHI Takahiro
@ 2019-02-08  8:15 ` AKASHI Takahiro
  2019-02-08  8:15 ` [U-Boot] [RFC v2 07/15] efi_loader: unicode_collation: converted " AKASHI Takahiro
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: AKASHI Takahiro @ 2019-02-08  8:15 UTC (permalink / raw)
  To: u-boot

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,
+};
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 07/15] efi_loader: unicode_collation: converted to DM
  2019-02-08  8:15 [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM AKASHI Takahiro
                   ` (5 preceding siblings ...)
  2019-02-08  8:15 ` [U-Boot] [RFC v2 06/15] efi_loader: device path: convert efi_device_path " AKASHI Takahiro
@ 2019-02-08  8:15 ` AKASHI Takahiro
  2019-02-08  8:15 ` [U-Boot] [RFC v2 08/15] efi_loader: console: convert efi console input/output " AKASHI Takahiro
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: AKASHI Takahiro @ 2019-02-08  8:15 UTC (permalink / raw)
  To: u-boot

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,
+};
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 08/15] efi_loader: console: convert efi console input/output to DM
  2019-02-08  8:15 [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM AKASHI Takahiro
                   ` (6 preceding siblings ...)
  2019-02-08  8:15 ` [U-Boot] [RFC v2 07/15] efi_loader: unicode_collation: converted " AKASHI Takahiro
@ 2019-02-08  8:15 ` AKASHI Takahiro
  2019-02-08  8:15 ` [U-Boot] [RFC v2 09/15] efi_loader: net: convert efi_net_obj " AKASHI Takahiro
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: AKASHI Takahiro @ 2019-02-08  8:15 UTC (permalink / raw)
  To: u-boot

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)
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 09/15] efi_loader: net: convert efi_net_obj to DM
  2019-02-08  8:15 [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM AKASHI Takahiro
                   ` (7 preceding siblings ...)
  2019-02-08  8:15 ` [U-Boot] [RFC v2 08/15] efi_loader: console: convert efi console input/output " AKASHI Takahiro
@ 2019-02-08  8:15 ` AKASHI Takahiro
  2019-02-08  8:15 ` [U-Boot] [RFC v2 10/15] efi_loader: gop: convert efi_gop_obj " AKASHI Takahiro
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: AKASHI Takahiro @ 2019-02-08  8:15 UTC (permalink / raw)
  To: u-boot

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
 }
 
 /*
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 10/15] efi_loader: gop: convert efi_gop_obj to DM
  2019-02-08  8:15 [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM AKASHI Takahiro
                   ` (8 preceding siblings ...)
  2019-02-08  8:15 ` [U-Boot] [RFC v2 09/15] efi_loader: net: convert efi_net_obj " AKASHI Takahiro
@ 2019-02-08  8:15 ` AKASHI Takahiro
  2019-02-08  8:15 ` [U-Boot] [RFC v2 11/15] dm: blk: add UCLASS_PARTITION AKASHI Takahiro
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: AKASHI Takahiro @ 2019-02-08  8:15 UTC (permalink / raw)
  To: u-boot

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;
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 11/15] dm: blk: add UCLASS_PARTITION
  2019-02-08  8:15 [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM AKASHI Takahiro
                   ` (9 preceding siblings ...)
  2019-02-08  8:15 ` [U-Boot] [RFC v2 10/15] efi_loader: gop: convert efi_gop_obj " AKASHI Takahiro
@ 2019-02-08  8:15 ` AKASHI Takahiro
  2019-02-08  8:15 ` [U-Boot] [RFC v2 12/15] efi_loader: disk: convert efi_disk_obj to DM AKASHI Takahiro
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: AKASHI Takahiro @ 2019-02-08  8:15 UTC (permalink / raw)
  To: u-boot

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 */
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 12/15] efi_loader: disk: convert efi_disk_obj to DM
  2019-02-08  8:15 [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM AKASHI Takahiro
                   ` (10 preceding siblings ...)
  2019-02-08  8:15 ` [U-Boot] [RFC v2 11/15] dm: blk: add UCLASS_PARTITION AKASHI Takahiro
@ 2019-02-08  8:15 ` AKASHI Takahiro
  2019-02-08  8:15 ` [U-Boot] [RFC v2 13/15] drivers: align block device drivers with DM-efi integration AKASHI Takahiro
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: AKASHI Takahiro @ 2019-02-08  8:15 UTC (permalink / raw)
  To: u-boot

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,
+};
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 13/15] drivers: align block device drivers with DM-efi integration
  2019-02-08  8:15 [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM AKASHI Takahiro
                   ` (11 preceding siblings ...)
  2019-02-08  8:15 ` [U-Boot] [RFC v2 12/15] efi_loader: disk: convert efi_disk_obj to DM AKASHI Takahiro
@ 2019-02-08  8:15 ` AKASHI Takahiro
  2019-02-08  8:15 ` [U-Boot] [RFC v2 14/15] efi_driver: converted to DM AKASHI Takahiro
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: AKASHI Takahiro @ 2019-02-08  8:15 UTC (permalink / raw)
  To: u-boot

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;
 }
 
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 14/15] efi_driver: converted to DM
  2019-02-08  8:15 [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM AKASHI Takahiro
                   ` (12 preceding siblings ...)
  2019-02-08  8:15 ` [U-Boot] [RFC v2 13/15] drivers: align block device drivers with DM-efi integration AKASHI Takahiro
@ 2019-02-08  8:15 ` AKASHI Takahiro
  2019-02-08  8:15 ` [U-Boot] [RFC v2 15/15] cmd: efidebug: aligned with DM-efi integration AKASHI Takahiro
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: AKASHI Takahiro @ 2019-02-08  8:15 UTC (permalink / raw)
  To: u-boot

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,
+};
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 15/15] cmd: efidebug: aligned with DM-efi integration
  2019-02-08  8:15 [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM AKASHI Takahiro
                   ` (13 preceding siblings ...)
  2019-02-08  8:15 ` [U-Boot] [RFC v2 14/15] efi_driver: converted to DM AKASHI Takahiro
@ 2019-02-08  8:15 ` AKASHI Takahiro
  2019-02-08  9:30 ` [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM Heinrich Schuchardt
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: AKASHI Takahiro @ 2019-02-08  8:15 UTC (permalink / raw)
  To: u-boot

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);
 
-- 
2.19.1

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM
  2019-02-08  8:15 [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM AKASHI Takahiro
                   ` (14 preceding siblings ...)
  2019-02-08  8:15 ` [U-Boot] [RFC v2 15/15] cmd: efidebug: aligned with DM-efi integration AKASHI Takahiro
@ 2019-02-08  9:30 ` Heinrich Schuchardt
  2019-02-09 23:00   ` Simon Glass
  2019-02-09 20:08 ` Simon Glass
  2019-02-09 23:04 ` Simon Glass
  17 siblings, 1 reply; 31+ messages in thread
From: Heinrich Schuchardt @ 2019-02-08  9:30 UTC (permalink / raw)
  To: u-boot



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 at c000000
>  virtio      0  [ + ]   virtio-mmio           |-- virtio_mmio at a000000
> 
>  [snip]
> 
>  pci         0  [ + ]   pci_generic_ecam      |-- pcie at 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 at 9010000
>  serial      0  [   ]   serial_pl01x          |-- pl011 at 9050000
>  serial      1  [ + ]   serial_pl01x          |-- pl011 at 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 at 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(-)
> 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 01/15] efi_loader: efi objects and protocols as DM devices
  2019-02-08  8:15 ` [U-Boot] [RFC v2 01/15] efi_loader: efi objects and protocols as DM devices AKASHI Takahiro
@ 2019-02-08 17:47   ` Heinrich Schuchardt
  2019-02-12  4:55     ` AKASHI Takahiro
  0 siblings, 1 reply; 31+ messages in thread
From: Heinrich Schuchardt @ 2019-02-08 17:47 UTC (permalink / raw)
  To: u-boot

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,
> +					  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),
> +};
> 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 02/15] efi_loader: boottime: convert efi_loaded_image_obj to DM
  2019-02-08  8:15 ` [U-Boot] [RFC v2 02/15] efi_loader: boottime: convert efi_loaded_image_obj to DM AKASHI Takahiro
@ 2019-02-08 17:53   ` Heinrich Schuchardt
  2019-02-12  5:07     ` AKASHI Takahiro
  0 siblings, 1 reply; 31+ messages in thread
From: Heinrich Schuchardt @ 2019-02-08 17:53 UTC (permalink / raw)
  To: u-boot

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,
> +		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,
> 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM
  2019-02-08  8:15 [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM AKASHI Takahiro
                   ` (15 preceding siblings ...)
  2019-02-08  9:30 ` [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM Heinrich Schuchardt
@ 2019-02-09 20:08 ` Simon Glass
  2019-02-12  8:25   ` AKASHI Takahiro
  2019-02-09 23:04 ` Simon Glass
  17 siblings, 1 reply; 31+ messages in thread
From: Simon Glass @ 2019-02-09 20:08 UTC (permalink / raw)
  To: u-boot

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

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM
  2019-02-08  9:30 ` [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM Heinrich Schuchardt
@ 2019-02-09 23:00   ` Simon Glass
  2019-02-12  7:24     ` AKASHI Takahiro
  0 siblings, 1 reply; 31+ messages in thread
From: Simon Glass @ 2019-02-09 23:00 UTC (permalink / raw)
  To: u-boot

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 at c000000
> >  virtio      0  [ + ]   virtio-mmio           |-- virtio_mmio at a000000
> >
> >  [snip]
> >
> >  pci         0  [ + ]   pci_generic_ecam      |-- pcie at 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 at 9010000
> >  serial      0  [   ]   serial_pl01x          |-- pl011 at 9050000
> >  serial      1  [ + ]   serial_pl01x          |-- pl011 at 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 at 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(-)
> >

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM
  2019-02-08  8:15 [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM AKASHI Takahiro
                   ` (16 preceding siblings ...)
  2019-02-09 20:08 ` Simon Glass
@ 2019-02-09 23:04 ` Simon Glass
  2019-02-12  8:30   ` AKASHI Takahiro
  17 siblings, 1 reply; 31+ messages in thread
From: Simon Glass @ 2019-02-09 23:04 UTC (permalink / raw)
  To: u-boot

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

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 01/15] efi_loader: efi objects and protocols as DM devices
  2019-02-08 17:47   ` Heinrich Schuchardt
@ 2019-02-12  4:55     ` AKASHI Takahiro
  0 siblings, 0 replies; 31+ messages in thread
From: AKASHI Takahiro @ 2019-02-12  4:55 UTC (permalink / raw)
  To: u-boot

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,
> > +					  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),
> > +};
> > 
> 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 02/15] efi_loader: boottime: convert efi_loaded_image_obj to DM
  2019-02-08 17:53   ` Heinrich Schuchardt
@ 2019-02-12  5:07     ` AKASHI Takahiro
  2019-02-12  6:47       ` Heinrich Schuchardt
  0 siblings, 1 reply; 31+ messages in thread
From: AKASHI Takahiro @ 2019-02-12  5:07 UTC (permalink / raw)
  To: u-boot

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,
> > +		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,
> > 
> 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 02/15] efi_loader: boottime: convert efi_loaded_image_obj to DM
  2019-02-12  5:07     ` AKASHI Takahiro
@ 2019-02-12  6:47       ` Heinrich Schuchardt
  2019-02-12  7:35         ` AKASHI Takahiro
  0 siblings, 1 reply; 31+ messages in thread
From: Heinrich Schuchardt @ 2019-02-12  6:47 UTC (permalink / raw)
  To: u-boot

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,
>>> +		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,
>>>
>>
> 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM
  2019-02-09 23:00   ` Simon Glass
@ 2019-02-12  7:24     ` AKASHI Takahiro
  2019-02-12  9:47       ` Heinrich Schuchardt
  0 siblings, 1 reply; 31+ messages in thread
From: AKASHI Takahiro @ 2019-02-12  7:24 UTC (permalink / raw)
  To: u-boot

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 at c000000
> > >  virtio      0  [ + ]   virtio-mmio           |-- virtio_mmio at a000000
> > >
> > >  [snip]
> > >
> > >  pci         0  [ + ]   pci_generic_ecam      |-- pcie at 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 at 9010000
> > >  serial      0  [   ]   serial_pl01x          |-- pl011 at 9050000
> > >  serial      1  [ + ]   serial_pl01x          |-- pl011 at 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 at 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(-)
> > >

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 02/15] efi_loader: boottime: convert efi_loaded_image_obj to DM
  2019-02-12  6:47       ` Heinrich Schuchardt
@ 2019-02-12  7:35         ` AKASHI Takahiro
  0 siblings, 0 replies; 31+ messages in thread
From: AKASHI Takahiro @ 2019-02-12  7:35 UTC (permalink / raw)
  To: u-boot

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,
> >>> +		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,
> >>>
> >>
> > 
> 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM
  2019-02-09 20:08 ` Simon Glass
@ 2019-02-12  8:25   ` AKASHI Takahiro
  0 siblings, 0 replies; 31+ messages in thread
From: AKASHI Takahiro @ 2019-02-12  8:25 UTC (permalink / raw)
  To: u-boot

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

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM
  2019-02-09 23:04 ` Simon Glass
@ 2019-02-12  8:30   ` AKASHI Takahiro
  0 siblings, 0 replies; 31+ messages in thread
From: AKASHI Takahiro @ 2019-02-12  8:30 UTC (permalink / raw)
  To: u-boot

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

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM
  2019-02-12  7:24     ` AKASHI Takahiro
@ 2019-02-12  9:47       ` Heinrich Schuchardt
  2019-03-19  1:25         ` Simon Glass
  0 siblings, 1 reply; 31+ messages in thread
From: Heinrich Schuchardt @ 2019-02-12  9:47 UTC (permalink / raw)
  To: u-boot



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 at c000000
>>>>  virtio      0  [ + ]   virtio-mmio           |-- virtio_mmio at a000000
>>>>
>>>>  [snip]
>>>>
>>>>  pci         0  [ + ]   pci_generic_ecam      |-- pcie at 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 at 9010000
>>>>  serial      0  [   ]   serial_pl01x          |-- pl011 at 9050000
>>>>  serial      1  [ + ]   serial_pl01x          |-- pl011 at 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 at 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(-)
>>>>
> 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM
  2019-02-12  9:47       ` Heinrich Schuchardt
@ 2019-03-19  1:25         ` Simon Glass
  0 siblings, 0 replies; 31+ messages in thread
From: Simon Glass @ 2019-03-19  1:25 UTC (permalink / raw)
  To: u-boot

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 at c000000
> >>>>  virtio      0  [ + ]   virtio-mmio           |-- virtio_mmio at a000000
> >>>>
> >>>>  [snip]
> >>>>
> >>>>  pci         0  [ + ]   pci_generic_ecam      |-- pcie at 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 at 9010000
> >>>>  serial      0  [   ]   serial_pl01x          |-- pl011 at 9050000
> >>>>  serial      1  [ + ]   serial_pl01x          |-- pl011 at 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 at 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(-)
> >>>>
> >

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2019-03-19  1:25 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-08  8:15 [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM AKASHI Takahiro
2019-02-08  8:15 ` [U-Boot] [RFC v2 01/15] efi_loader: efi objects and protocols as DM devices AKASHI Takahiro
2019-02-08 17:47   ` Heinrich Schuchardt
2019-02-12  4:55     ` AKASHI Takahiro
2019-02-08  8:15 ` [U-Boot] [RFC v2 02/15] efi_loader: boottime: convert efi_loaded_image_obj to DM AKASHI Takahiro
2019-02-08 17:53   ` Heinrich Schuchardt
2019-02-12  5:07     ` AKASHI Takahiro
2019-02-12  6:47       ` Heinrich Schuchardt
2019-02-12  7:35         ` AKASHI Takahiro
2019-02-08  8:15 ` [U-Boot] [RFC v2 03/15] efi_loader: image_loader: aligned with DM AKASHI Takahiro
2019-02-08  8:15 ` [U-Boot] [RFC v2 04/15] efi_driver: rename UCLASS_EFI to UCLASS_EFI_DRIVER AKASHI Takahiro
2019-02-08  8:15 ` [U-Boot] [RFC v2 05/15] efi_loader: convert efi_root_node to DM AKASHI Takahiro
2019-02-08  8:15 ` [U-Boot] [RFC v2 06/15] efi_loader: device path: convert efi_device_path " AKASHI Takahiro
2019-02-08  8:15 ` [U-Boot] [RFC v2 07/15] efi_loader: unicode_collation: converted " AKASHI Takahiro
2019-02-08  8:15 ` [U-Boot] [RFC v2 08/15] efi_loader: console: convert efi console input/output " AKASHI Takahiro
2019-02-08  8:15 ` [U-Boot] [RFC v2 09/15] efi_loader: net: convert efi_net_obj " AKASHI Takahiro
2019-02-08  8:15 ` [U-Boot] [RFC v2 10/15] efi_loader: gop: convert efi_gop_obj " AKASHI Takahiro
2019-02-08  8:15 ` [U-Boot] [RFC v2 11/15] dm: blk: add UCLASS_PARTITION AKASHI Takahiro
2019-02-08  8:15 ` [U-Boot] [RFC v2 12/15] efi_loader: disk: convert efi_disk_obj to DM AKASHI Takahiro
2019-02-08  8:15 ` [U-Boot] [RFC v2 13/15] drivers: align block device drivers with DM-efi integration AKASHI Takahiro
2019-02-08  8:15 ` [U-Boot] [RFC v2 14/15] efi_driver: converted to DM AKASHI Takahiro
2019-02-08  8:15 ` [U-Boot] [RFC v2 15/15] cmd: efidebug: aligned with DM-efi integration AKASHI Takahiro
2019-02-08  9:30 ` [U-Boot] [RFC v2 00/15] dm, efi: integrate efi objects into DM Heinrich Schuchardt
2019-02-09 23:00   ` Simon Glass
2019-02-12  7:24     ` AKASHI Takahiro
2019-02-12  9:47       ` Heinrich Schuchardt
2019-03-19  1:25         ` Simon Glass
2019-02-09 20:08 ` Simon Glass
2019-02-12  8:25   ` AKASHI Takahiro
2019-02-09 23:04 ` Simon Glass
2019-02-12  8:30   ` AKASHI Takahiro

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.