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 <[email protected]>
> > ---
> >  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),
> > +};
> > 
> 
_______________________________________________
U-Boot mailing list
[email protected]
https://lists.denx.de/listinfo/u-boot

Reply via email to