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