Hi Heinrick, On 17 December 2017 at 08:43, Heinrich Schuchardt <xypron.g...@gmx.de> wrote: > Implement the ConnectController boot service. > > Signed-off-by: Heinrich Schuchardt <xypron.g...@gmx.de> > --- > include/efi_api.h | 22 ++++++ > include/efi_loader.h | 2 + > lib/efi_loader/efi_boottime.c | 178 > ++++++++++++++++++++++++++++++++++++------ > 3 files changed, 178 insertions(+), 24 deletions(-)
Reviewed-by: Simon Glass <s...@chromium.org> Please see below. Also please mention when tests come for these. > > diff --git a/include/efi_api.h b/include/efi_api.h > index 46963f2891..81e580dbbc 100644 > --- a/include/efi_api.h > +++ b/include/efi_api.h > @@ -805,4 +805,26 @@ struct efi_file_info { > s16 file_name[0]; > }; > > +#define EFI_DRIVER_BINDING_PROTOCOL_GUID \ > + EFI_GUID(0x18a031ab, 0xb443, 0x4d1a,\ > + 0xa5, 0xc0, 0x0c, 0x09, 0x26, 0x1e, 0x9f, 0x71) > +struct efi_driver_binding_protocol { > + efi_status_t (EFIAPI * supported)( > + struct efi_driver_binding_protocol *this, > + efi_handle_t controller_handle, > + struct efi_device_path *remaining_device_path); > + efi_status_t (EFIAPI * start)( > + struct efi_driver_binding_protocol *this, > + efi_handle_t controller_handle, > + struct efi_device_path *remaining_device_path); > + efi_status_t (EFIAPI * stop)( > + struct efi_driver_binding_protocol *this, > + efi_handle_t controller_handle, > + efi_uintn_t number_of_children, > + efi_handle_t *child_handle_buffer); > + u32 version; > + efi_handle_t image_handle; > + efi_handle_t driver_binding_handle; > +}; > + > #endif > diff --git a/include/efi_loader.h b/include/efi_loader.h > index 637e6e166d..9e1ae8866b 100644 > --- a/include/efi_loader.h > +++ b/include/efi_loader.h > @@ -88,6 +88,8 @@ uint16_t *efi_dp_str(struct efi_device_path *dp); > extern const efi_guid_t efi_global_variable_guid; > extern const efi_guid_t efi_guid_console_control; > extern const efi_guid_t efi_guid_device_path; > +/* GUID of the EFI_DRIVER_BINDING_PROTOCOL */ > +extern const efi_guid_t efi_guid_driver_binding_protocol; > extern const efi_guid_t efi_guid_loaded_image; > extern const efi_guid_t efi_guid_device_path_to_text_protocol; > extern const efi_guid_t efi_simple_file_system_protocol_guid; > diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c > index b5d6808bf7..6cc0659eb9 100644 > --- a/lib/efi_loader/efi_boottime.c > +++ b/lib/efi_loader/efi_boottime.c > @@ -56,6 +56,9 @@ static volatile void *efi_gd, *app_gd; > > static int entry_count; > static int nesting_level; > +/* GUID of the EFI_DRIVER_BINDING_PROTOCOL */ > +const efi_guid_t efi_guid_driver_binding_protocol = > + EFI_DRIVER_BINDING_PROTOCOL_GUID; > > /* Called on every callback entry */ > int __efi_entry_check(void) > @@ -1619,30 +1622,6 @@ static efi_status_t EFIAPI > efi_set_watchdog_timer(unsigned long timeout, > return EFI_EXIT(efi_set_watchdog(timeout)); > } > > -/* > - * Connect a controller to a driver. > - * > - * This function implements the ConnectController service. > - * See the Unified Extensible Firmware Interface (UEFI) specification > - * for details. > - * > - * @controller_handle handle of the controller > - * @driver_image_handle handle of the driver > - * @remain_device_path device path of a child controller > - * @recursive true to connect all child controllers > - * @return status code > - */ > -static efi_status_t EFIAPI efi_connect_controller( > - efi_handle_t controller_handle, > - efi_handle_t *driver_image_handle, > - struct efi_device_path *remain_device_path, > - bool recursive) > -{ > - EFI_ENTRY("%p, %p, %p, %d", controller_handle, driver_image_handle, > - remain_device_path, recursive); > - return EFI_EXIT(EFI_NOT_FOUND); > -} > - > /* > * Disconnect a controller from a driver. > * > @@ -2352,6 +2331,157 @@ static efi_status_t EFIAPI efi_handle_protocol(void > *handle, > NULL, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL); > } > > +static efi_status_t efi_bind_controller( > + efi_handle_t controller_handle, > + efi_handle_t driver_image_handle, > + struct efi_device_path *remain_device_path) > +{ > + struct efi_driver_binding_protocol *binding_protocol; > + efi_status_t r; > + > + r = EFI_CALL(efi_open_protocol(driver_image_handle, > + &efi_guid_driver_binding_protocol, > + (void **)&binding_protocol, > + driver_image_handle, NULL, > + EFI_OPEN_PROTOCOL_GET_PROTOCOL)); > + if (r != EFI_SUCCESS) > + return r; > + r = EFI_CALL(binding_protocol->supported(binding_protocol, > + controller_handle, > + remain_device_path)); > + if (r == EFI_SUCCESS) > + r = EFI_CALL(binding_protocol->start(binding_protocol, > + controller_handle, > + remain_device_path)); > + EFI_CALL(efi_close_protocol(driver_image_handle, > + &efi_guid_driver_binding_protocol, > + driver_image_handle, NULL)); > + return r; > +} > + > +static efi_status_t efi_connect_single_controller( > + efi_handle_t controller_handle, > + efi_handle_t *driver_image_handle, > + struct efi_device_path *remain_device_path) > +{ > + efi_handle_t *buffer; > + size_t count; > + size_t i; > + efi_status_t r; > + size_t connected = 0; > + > + /* Get buffer with all handles with driver binding protocol */ > + r = EFI_CALL(efi_locate_handle_buffer(BY_PROTOCOL, > + > &efi_guid_driver_binding_protocol, > + NULL, &count, &buffer)); > + if (r != EFI_SUCCESS) > + return r; > + > + /* Context Override */ > + if (driver_image_handle) { > + for (; *driver_image_handle; ++driver_image_handle) { > + for (i = 0; i < count; ++i) { > + if (buffer[i] == *driver_image_handle) { > + buffer[i] = NULL; > + r = efi_bind_controller( > + controller_handle, > + *driver_image_handle, > + remain_device_path); > + if (r == EFI_SUCCESS) > + ++connected; What happens to any error here? > + } > + } > + } > + } > + > + /* > + * TODO: Some overrides are not yet implemented: > + * - Platform Driver Override > + * - Driver Family Override Search > + * - Bus Specific Driver Override Bus-specific ? > + */ > + > + /* Driver Binding Search */ > + for (i = 0; i < count; ++i) { > + if (buffer[i]) { > + r = efi_bind_controller(controller_handle, > + buffer[i], > + remain_device_path); > + if (r == EFI_SUCCESS) > + ++connected; > + } > + } > + > + efi_free_pool(buffer); > + if (!connected) > + return EFI_NOT_FOUND; > + return EFI_SUCCESS; > +} > + > +/* > + * Connect a controller to a driver. > + * > + * This function implements the ConnectController service. > + * See the Unified Extensible Firmware Interface (UEFI) specification > + * for details. Well I think it would be good to explain briefly what it does. > + * > + * @controller_handle handle of the controller > + * @driver_image_handle handle of the driver > + * @remain_device_path device path of a child controller > + * @recursive true to connect all child controllers > + * @return status code > + */ > +static efi_status_t EFIAPI efi_connect_controller( > + efi_handle_t controller_handle, > + efi_handle_t *driver_image_handle, > + struct efi_device_path *remain_device_path, > + bool recursive) > +{ > + 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; > + } > + > + r = efi_connect_single_controller(controller_handle, > + driver_image_handle, > + remain_device_path); > + if (r == EFI_SUCCESS) > + ret = EFI_SUCCESS; > + if (recursive) { > + struct efi_handler *handler; > + struct efi_open_protocol_info_item *item; > + > + list_for_each_entry(handler, &efiobj->protocols, link) { > + list_for_each_entry(item, &handler->open_infos, link) > { > + if (item->info.attributes & > + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) { > + r = EFI_CALL(efi_connect_controller( > + item->info.controller_handle, > + driver_image_handle, > + remain_device_path, > + recursive)); > + if (r == EFI_SUCCESS) > + ret = EFI_SUCCESS; > + } > + } > + } > + } > + /* Check for child controller specified by end node */ > + if (ret != EFI_SUCCESS && remain_device_path && > + remain_device_path->type == DEVICE_PATH_TYPE_END) > + ret = EFI_SUCCESS; > +out: > + return EFI_EXIT(ret); > +} > + > static const struct efi_boot_services efi_boot_services = { > .hdr = { > .headersize = sizeof(struct efi_table_hdr), > -- > 2.14.2 > Regards, Simon _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot