From mboxrd@z Thu Jan 1 00:00:00 1970 From: AKASHI Takahiro Date: Tue, 12 Feb 2019 13:55:19 +0900 Subject: [U-Boot] [RFC v2 01/15] efi_loader: efi objects and protocols as DM devices In-Reply-To: <808dac7f-94bc-9af1-99eb-78597b91d386@gmx.de> References: <20190208081542.2813-1-takahiro.akashi@linaro.org> <20190208081542.2813-2-takahiro.akashi@linaro.org> <808dac7f-94bc-9af1-99eb-78597b91d386@gmx.de> Message-ID: <20190212045518.GH20286@linaro.org> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de 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 > > --- > > 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 > > #include > > +#include > > +#include > > +#include > > +#include > > #include > > #include > > #include > > @@ -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), > > +}; > > >