[U-Boot] [PATCH v3 3/8] cmd: efishell: add drivers command

Heinrich Schuchardt
2018-12-25T12:07:44Z

On 12/25/18 8:22 AM, AKASHI Takahiro wrote:
> On Thu, Dec 20, 2018 at 08:51:34AM +0100, Heinrich Schuchardt wrote:
>> On 12/18/18 6:05 AM, AKASHI Takahiro wrote:
>>> "drivers" command prints all the uefi drivers on the system.
>>> => efi drivers
>>> Driver Name Image Path
>>> ============================================
>>> (unknown) <NULL>+(not found)
>>> guid: 18a031ab-b443-4d1a-a5c0-0c09261e9f71
>>>
>>> Currently, no useful information can be printed.
>>
>> Why? We have lib/efi_driver/efi_block_device.c. So you should be able to
>> test the output.
>
> There are a couple of reasons that I think there are no useful
> information:
> 1. EFI driver doesn't have any printable name.
> A corresponding u-boot driver, efi_block in efi_block_device.c,
> has a name, but there is not direct link between efi driver
> and this u-boot driver. So it's not easy to find a name for efi driver.
> 2. I will fix this by adding a "name" field to
> efi_driver_binding_extended_protocol, but if even so, we can only
> say "EFI block driver." We have no chance to know about controller
> -specific, say USB, SCSI or anything, information.

I would just stick to the standard. The following information can be
provided in the standard:

Loop over all handles implementing the driver binding protocol and output:

- address of driver handle
- device path (if installed on the handle)

>
> 3. More importantly, efi block devices can be defined in two ways,
> via efi_uclass/efi_block_device and efi_disk. The latter supports
> BLOCK_IO_PROTOCOL binding having any associated driver/controller.
> It seems to me that it's quite confusion.

lib/efi_driver/efi_block_device.c is used when an EFI binary creates a
new block device. E.g. when iPXE connects to an iSCSI drive it creates a
handle with the the block io protocol and call ConnectControllers. Now
our efi_block_device binds to the handle, identifies the partitions, and
provides the simple file system protocol.

Unfortunately the migration of all block devices to the driver model has
been delayed to July 2019 (cf. doc/driver-model/MIGRATION.txt). Once it
is completed we can clean up the code.

Best regards

Heinrich

>
> Thanks,
> -Takahiro Akashi
>
>
>
>> Best regards
>>
>> Heirnich
>>
>>>
>>> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
>>> ---
>>> cmd/efishell.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++-
>>> 1 file changed, 94 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/cmd/efishell.c b/cmd/efishell.c
>>> index 929b6343b1b2..ed8de9e0355d 100644
>>> --- a/cmd/efishell.c
>>> +++ b/cmd/efishell.c
>>> @@ -343,6 +343,95 @@ static int do_efi_show_devices(int argc, char * const argv[])
>>> return CMD_RET_SUCCESS;
>>> }
>>>
>>> +static int efi_get_driver_handle_info(efi_handle_t handle, u16 **name,
>>> + u16 **devname, u16 **filename)
>>> +{
>>> + struct efi_driver_binding_protocol *binding;
>>> + struct efi_loaded_image *image;
>>> + efi_status_t ret;
>>> +
>>> + ret = bs->open_protocol(handle, &efi_guid_driver_binding_protocol,
>>> + (void **)&binding, NULL, NULL,
>>> + EFI_OPEN_PROTOCOL_GET_PROTOCOL);
>>> + if (ret != EFI_SUCCESS)
>>> + return -1;
>>> +
>>> + ret = bs->open_protocol(binding->image_handle, &efi_guid_loaded_image,
>>> + (void **)&image, NULL /* FIXME */, NULL,
>>> + EFI_OPEN_PROTOCOL_GET_PROTOCOL);
>>> + if (ret != EFI_SUCCESS)
>>> + goto e_out;
>>> +
>>> + /*
>>> + * TODO:
>>> + * handle image->device_handle,
>>> + * use append_device_path()
>>> + */
>>> + *devname = NULL;
>>> + *filename = efi_dp_str(image->file_path);
>>> +
>>> + return 0;
>>> +
>>> +e_out:
>>> + *devname = NULL;
>>> + *filename = NULL;
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static int do_efi_show_drivers(int argc, char * const argv[])
>>> +{
>>> + efi_handle_t *handles = NULL, *handle;
>>> + efi_uintn_t size = 0;
>>> + u16 *drvname, *devname, *filename;
>>> + efi_status_t ret;
>>> + int i;
>>> +
>>> + ret = bs->locate_handle(BY_PROTOCOL, &efi_guid_driver_binding_protocol,
>>> + NULL, &size, NULL);
>>> + if (ret == EFI_BUFFER_TOO_SMALL) {
>>> + handles = calloc(1, size);
>>> + if (!handles)
>>> + return CMD_RET_FAILURE;
>>> +
>>> + ret = bs->locate_handle(BY_PROTOCOL,
>>> + &efi_guid_driver_binding_protocol,
>>> + NULL, &size, handles);
>>> + }
>>> + if (ret != EFI_SUCCESS) {
>>> + free(handles);
>>> + return CMD_RET_FAILURE;
>>> + }
>>> +
>>> + printf("Driver Name Image Path\n");
>>> + printf("============================================\n");
>>> + handle = handles;
>>> + for (i = 0; i < size / sizeof(*handle); i++) {
>>> + if (!efi_get_driver_handle_info(*handle, &drvname, &devname,
>>> + &filename)) {
>>> + printf("%-16s%ls+%ls\n",
>>> + "(unknown)", devname, filename);
>>> + efi_free_pool(devname);
>>> + efi_free_pool(filename);
>>> +
>>> + /* TODO: no other info */
>>> + struct efi_object *efiobj;
>>> + struct list_head *lhandle;
>>> + struct efi_handler *protocol;
>>> +
>>> + efiobj = efi_search_obj(*handle);
>>> + list_for_each(lhandle, &efiobj->protocols) {
>>> + protocol = list_entry(lhandle,
>>> + struct efi_handler, link);
>>> + printf(" guid: %pUl\n", protocol->guid);
>>> + }
>>> + }
>>> + handle++;
>>> + }
>>> +
>>> + return CMD_RET_SUCCESS;
>>> +}
>>> +
>>> static int do_efi_boot_add(int argc, char * const argv[])
>>> {
>>> int id;
>>> @@ -726,6 +815,8 @@ static int do_efishell(cmd_tbl_t *cmdtp, int flag,
>>> return do_efi_set_var(argc, argv);
>>> else if (!strcmp(command, "devices"))
>>> return do_efi_show_devices(argc, argv);
>>> + else if (!strcmp(command, "drivers"))
>>> + return do_efi_show_drivers(argc, argv);
>>> else
>>> return CMD_RET_USAGE;
>>> }
>>> @@ -749,7 +840,9 @@ static char efishell_help_text[] =
>>> " - set/delete uefi variable's value\n"
>>> " <value> may be \"=\"...\"\", \"=0x...\" (set) or \"=\" (delete)\n"
>>> "efishell devices\n"
>>> - " - show uefi devices\n";
>>> + " - show uefi devices\n"
>>> + "efishell drivers\n"
>>> + " - show uefi drivers\n";
>>> #endif
>>>
>>> U_BOOT_CMD(
>>>
>>
>