mbox series

[U-Boot,v2,00/18] efi_loader: enable EFI driver provided block device

Message ID 20180117191612.17108-1-xypron.glpk@gmx.de
Headers show
Series efi_loader: enable EFI driver provided block device | expand

Message

Heinrich Schuchardt Jan. 17, 2018, 7:15 p.m. UTC
With this patch series an EFI application or driver can supply
a block device which in turn can be used to download an image.

E.g. we can load iPXE, connect iSCSI drives, download grub from the
SAN and afterwards with grub download and run an EFI application.
Booting Linux from an iSCSI drive was successful on arm64.

v2:
	Add an additional patch to fix ExitBootServices.
	Provide comments for EFI block driver.
	Avoid printing when not in debug mode
	Add product tools/file2include to .gitignore.
	Put the patch with the test for block io after the patch for the
	driver.

Heinrich Schuchardt (18):
  efi_loader: return NULL from device path functions
  efi_loader: address of the simple file system protocol
  efi_loader: correct find simple file system protocol
  efi_loader: print device path when entering efi_load_image
  efi_loader: allocate correct memory type for EFI image
  efi_loader: check tables in helloworld.efi
  efi_loader: fix StartImage bootservice
  efi_loader: efi_disk_register: correctly determine if_type_name
  efi_loader: make efi_block_io_guid a global symbol
  efi_loader: provide a function to create a partition node
  efi_loader: make efi_disk_create_partitions a global symbol
  efi_loader: correct EFI_BLOCK_IO_PROTOCOL definitions
  efi_loader: provide function to get last node of a device path
  efi_loader: provide links between devices EFI handles
  tools: provide a tool to convert a binary file to an include
  efi_driver: EFI block driver
  efi_selftest: provide a test for block io
  efi_loader: fix ExitBootServices

 MAINTAINERS                                  |   1 +
 common/board_r.c                             |   3 +
 drivers/block/blk-uclass.c                   |   4 +-
 include/blk.h                                |   1 +
 include/config_fallbacks.h                   |   1 +
 include/dm/device.h                          |   4 +
 include/dm/uclass-id.h                       |   1 +
 include/efi_api.h                            |  16 +-
 include/efi_driver.h                         |  30 ++
 include/efi_loader.h                         |  21 +-
 lib/Makefile                                 |   1 +
 lib/efi_driver/Makefile                      |  13 +
 lib/efi_driver/efi_block_device.c            | 175 ++++++++++++
 lib/efi_driver/efi_uclass.c                  | 330 ++++++++++++++++++++++
 lib/efi_loader/efi_boottime.c                |  42 ++-
 lib/efi_loader/efi_device_path.c             | 168 +++++++++---
 lib/efi_loader/efi_disk.c                    | 137 +++++++---
 lib/efi_loader/efi_image_loader.c            |  64 +++--
 lib/efi_loader/helloworld.c                  |  26 ++
 lib/efi_selftest/Makefile                    |   4 +
 lib/efi_selftest/efi_selftest_block_device.c | 395 +++++++++++++++++++++++++++
 lib/efi_selftest/efi_selftest_disk_image.h   |  69 +++++
 tools/.gitignore                             |   1 +
 tools/Makefile                               |   3 +
 tools/file2include.c                         | 106 +++++++
 25 files changed, 1493 insertions(+), 123 deletions(-)
 create mode 100644 include/efi_driver.h
 create mode 100644 lib/efi_driver/Makefile
 create mode 100644 lib/efi_driver/efi_block_device.c
 create mode 100644 lib/efi_driver/efi_uclass.c
 create mode 100644 lib/efi_selftest/efi_selftest_block_device.c
 create mode 100644 lib/efi_selftest/efi_selftest_disk_image.h
 create mode 100644 tools/file2include.c

Comments

Simon Glass Jan. 18, 2018, 11 p.m. UTC | #1
Hi Heinrich,

On 17 January 2018 at 11:15, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
> With this patch series an EFI application or driver can supply
> a block device which in turn can be used to download an image.
>
> E.g. we can load iPXE, connect iSCSI drives, download grub from the
> SAN and afterwards with grub download and run an EFI application.
> Booting Linux from an iSCSI drive was successful on arm64.
>
> v2:
>         Add an additional patch to fix ExitBootServices.
>         Provide comments for EFI block driver.
>         Avoid printing when not in debug mode
>         Add product tools/file2include to .gitignore.
>         Put the patch with the test for block io after the patch for the
>         driver.
>
> Heinrich Schuchardt (18):
>   efi_loader: return NULL from device path functions
>   efi_loader: address of the simple file system protocol
>   efi_loader: correct find simple file system protocol
>   efi_loader: print device path when entering efi_load_image
>   efi_loader: allocate correct memory type for EFI image
>   efi_loader: check tables in helloworld.efi
>   efi_loader: fix StartImage bootservice
>   efi_loader: efi_disk_register: correctly determine if_type_name
>   efi_loader: make efi_block_io_guid a global symbol
>   efi_loader: provide a function to create a partition node
>   efi_loader: make efi_disk_create_partitions a global symbol
>   efi_loader: correct EFI_BLOCK_IO_PROTOCOL definitions
>   efi_loader: provide function to get last node of a device path
>   efi_loader: provide links between devices EFI handles
>   tools: provide a tool to convert a binary file to an include
>   efi_driver: EFI block driver
>   efi_selftest: provide a test for block io
>   efi_loader: fix ExitBootServices
>
>  MAINTAINERS                                  |   1 +
>  common/board_r.c                             |   3 +
>  drivers/block/blk-uclass.c                   |   4 +-
>  include/blk.h                                |   1 +
>  include/config_fallbacks.h                   |   1 +
>  include/dm/device.h                          |   4 +
>  include/dm/uclass-id.h                       |   1 +
>  include/efi_api.h                            |  16 +-
>  include/efi_driver.h                         |  30 ++
>  include/efi_loader.h                         |  21 +-
>  lib/Makefile                                 |   1 +
>  lib/efi_driver/Makefile                      |  13 +
>  lib/efi_driver/efi_block_device.c            | 175 ++++++++++++
>  lib/efi_driver/efi_uclass.c                  | 330 ++++++++++++++++++++++
>  lib/efi_loader/efi_boottime.c                |  42 ++-
>  lib/efi_loader/efi_device_path.c             | 168 +++++++++---
>  lib/efi_loader/efi_disk.c                    | 137 +++++++---
>  lib/efi_loader/efi_image_loader.c            |  64 +++--
>  lib/efi_loader/helloworld.c                  |  26 ++
>  lib/efi_selftest/Makefile                    |   4 +
>  lib/efi_selftest/efi_selftest_block_device.c | 395 +++++++++++++++++++++++++++
>  lib/efi_selftest/efi_selftest_disk_image.h   |  69 +++++
>  tools/.gitignore                             |   1 +
>  tools/Makefile                               |   3 +
>  tools/file2include.c                         | 106 +++++++
>  25 files changed, 1493 insertions(+), 123 deletions(-)
>  create mode 100644 include/efi_driver.h
>  create mode 100644 lib/efi_driver/Makefile
>  create mode 100644 lib/efi_driver/efi_block_device.c
>  create mode 100644 lib/efi_driver/efi_uclass.c
>  create mode 100644 lib/efi_selftest/efi_selftest_block_device.c
>  create mode 100644 lib/efi_selftest/efi_selftest_disk_image.h
>  create mode 100644 tools/file2include.c
>
> --
> 2.14.2
>

Do you have a git tree with these patches? I get errors when applying them.

Some general comments for discussion, based on my limited understanding.

At present from what I can tell, this looks through the UCLASS_EFI
drivers and instantiates a EFI driver/device for each. But it does not
seem to relate this to the U-Boot driver. It seems in fact to create a
new device. For example efi_bl_bind() calls blk_create_device().

Instead I think there should be a real driver-rmodel device creasted
with UCLASS_EFI. It should be a child of the DM UCLASS_BLK device. The
could work in a similar way to now, except that it can scan DM devices
of a particular UCLASS rather than scanning DM drivers.

Also the patch that creates a tool to generate a binary as a header
file - can we use the same method as we use for other embedding? See
for example how .dtb is done.

Regards,
Simon
Heinrich Schuchardt Jan. 19, 2018, 7:41 a.m. UTC | #2
On 01/19/2018 12:00 AM, Simon Glass wrote:
> Hi Heinrich,
> 
> On 17 January 2018 at 11:15, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>> With this patch series an EFI application or driver can supply
>> a block device which in turn can be used to download an image.
>>
>> E.g. we can load iPXE, connect iSCSI drives, download grub from the
>> SAN and afterwards with grub download and run an EFI application.
>> Booting Linux from an iSCSI drive was successful on arm64.
>>
>> v2:
>>          Add an additional patch to fix ExitBootServices.
>>          Provide comments for EFI block driver.
>>          Avoid printing when not in debug mode
>>          Add product tools/file2include to .gitignore.
>>          Put the patch with the test for block io after the patch for the
>>          driver.
>>
>> Heinrich Schuchardt (18):
>>    efi_loader: return NULL from device path functions
>>    efi_loader: address of the simple file system protocol
>>    efi_loader: correct find simple file system protocol
>>    efi_loader: print device path when entering efi_load_image
>>    efi_loader: allocate correct memory type for EFI image
>>    efi_loader: check tables in helloworld.efi
>>    efi_loader: fix StartImage bootservice
>>    efi_loader: efi_disk_register: correctly determine if_type_name
>>    efi_loader: make efi_block_io_guid a global symbol
>>    efi_loader: provide a function to create a partition node
>>    efi_loader: make efi_disk_create_partitions a global symbol
>>    efi_loader: correct EFI_BLOCK_IO_PROTOCOL definitions
>>    efi_loader: provide function to get last node of a device path
>>    efi_loader: provide links between devices EFI handles
>>    tools: provide a tool to convert a binary file to an include
>>    efi_driver: EFI block driver
>>    efi_selftest: provide a test for block io
>>    efi_loader: fix ExitBootServices
>>
>>   MAINTAINERS                                  |   1 +
>>   common/board_r.c                             |   3 +
>>   drivers/block/blk-uclass.c                   |   4 +-
>>   include/blk.h                                |   1 +
>>   include/config_fallbacks.h                   |   1 +
>>   include/dm/device.h                          |   4 +
>>   include/dm/uclass-id.h                       |   1 +
>>   include/efi_api.h                            |  16 +-
>>   include/efi_driver.h                         |  30 ++
>>   include/efi_loader.h                         |  21 +-
>>   lib/Makefile                                 |   1 +
>>   lib/efi_driver/Makefile                      |  13 +
>>   lib/efi_driver/efi_block_device.c            | 175 ++++++++++++
>>   lib/efi_driver/efi_uclass.c                  | 330 ++++++++++++++++++++++
>>   lib/efi_loader/efi_boottime.c                |  42 ++-
>>   lib/efi_loader/efi_device_path.c             | 168 +++++++++---
>>   lib/efi_loader/efi_disk.c                    | 137 +++++++---
>>   lib/efi_loader/efi_image_loader.c            |  64 +++--
>>   lib/efi_loader/helloworld.c                  |  26 ++
>>   lib/efi_selftest/Makefile                    |   4 +
>>   lib/efi_selftest/efi_selftest_block_device.c | 395 +++++++++++++++++++++++++++
>>   lib/efi_selftest/efi_selftest_disk_image.h   |  69 +++++
>>   tools/.gitignore                             |   1 +
>>   tools/Makefile                               |   3 +
>>   tools/file2include.c                         | 106 +++++++
>>   25 files changed, 1493 insertions(+), 123 deletions(-)
>>   create mode 100644 include/efi_driver.h
>>   create mode 100644 lib/efi_driver/Makefile
>>   create mode 100644 lib/efi_driver/efi_block_device.c
>>   create mode 100644 lib/efi_driver/efi_uclass.c
>>   create mode 100644 lib/efi_selftest/efi_selftest_block_device.c
>>   create mode 100644 lib/efi_selftest/efi_selftest_disk_image.h
>>   create mode 100644 tools/file2include.c
>>
>> --
>> 2.14.2
>>
> 
> Do you have a git tree with these patches? I get errors when applying them.

https://github.com/xypron2/u-boot.git
branch efi-2018-03-rc1

> 
> Some general comments for discussion, based on my limited understanding.
> 
> At present from what I can tell, this looks through the UCLASS_EFI
> drivers and instantiates a EFI driver/device for each. But it does not
> seem to relate this to the U-Boot driver. It seems in fact to create a
> new device. For example efi_bl_bind() calls blk_create_device().

It is important to understand the sequence of events:

U-Boot creates the EFI uclass.
This uclass iterates over all EFI drivers (only one up to now).
For each driver it creates a handle.
on the handle it install the EFI_DRIVER_BINDING protocol.
U-Boot loads iPXE.
iPXE creates connects to a target on an iSCSI server

Up to this point the iSCSI drive that we want to connect to as a block 
device is completely unknown to U-Boot.

iPXE creates a handle for the target and installs the 
EFI_BLOCK_IO_PROTOCOL on the handle.
iPXE calls ConnectController for this handle (which is referred to as 
controller).
efi_connect_controller() loops over all handles implementing the 
EFI_DRIVER_BINDING protocol and calls the supported() method of the 
protocol to identify a driver supporting the controller.
For each driver supporting the controller the start() method is called.

The supported() and start() methods are implemented in the EFI uclass.
In the supported() and start() methods the protocol GUID exposed by the 
EFI driver is compared to the GUIDS of the protocols installed on the 
controller to find a match.
If a match is found the EFI uclass calls the bind function of the EFI 
driver.

The EFI block driver now creates a block device.
For the block device it creates partitions.
On the partitions it installs the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL.
The EFI block driver has a read (efi_bl_read) and a write (efi_bl_write) 
function.
These delegate reads and writes to the EFI_BLOCK_IO_PROTOCOL.

Now iPXE tries to load grub.
It calls the OpenVolume method of the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL of 
the partition to get an instance of the EFI_FILE_PROTOCOL.
iPXE calls the Open method of the EFI_FILE_PROTOCOL with the path to grub.
This method is implemented in efi_file_open().
efi_file_open calls fs_exists() which calls ext4fs_exitsts() which calls 
the read method of the block device created by the EFI block driver. 
This method is implemented in efi_bl_read().
efi_bl_read() calls the read_blocks() method of the 
EFI_BLOCK_IO_PROTOCOL exposed by iPXE.
iPXE now uses the iSCSI protocol to read the requested blocks from the 
iSCSI server.


> 
> Instead I think there should be a real driver-rmodel device creasted
> with UCLASS_EFI. It should be a child of the DM UCLASS_BLK device. The
> could work in a similar way to now, except that it can scan DM devices
> of a particular UCLASS rather than scanning DM drivers.
> 

There is nothing to scan before the EFI application is running.
The starting point is ConnectController being called by the EFI application

The EFI uclass is not specific to block devices. It is responsible for 
all future EFI drivers. These could support any kind of virtual devices, 
e.g. a network interface.

> Also the patch that creates a tool to generate a binary as a header
> file - can we use the same method as we use for other embedding? See
> for example how .dtb is done.

I avoid embedding a 64kiB disk image. My include results in 728 bytes in 
the binary. I really want compression here.

With further patches I have to include binaries again which compress nicely.

Regards

Heinrich

> 
> Regards,
> Simon
>
Simon Glass Jan. 22, 2018, 12:30 a.m. UTC | #3
Hi Heinrich,

On 19 January 2018 at 00:41, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
> On 01/19/2018 12:00 AM, Simon Glass wrote:
>>
>> Hi Heinrich,
>>
>> On 17 January 2018 at 11:15, Heinrich Schuchardt <xypron.glpk@gmx.de>
>> wrote:
>>>
>>> With this patch series an EFI application or driver can supply
>>> a block device which in turn can be used to download an image.
>>>
>>> E.g. we can load iPXE, connect iSCSI drives, download grub from the
>>> SAN and afterwards with grub download and run an EFI application.
>>> Booting Linux from an iSCSI drive was successful on arm64.
>>>
>>> v2:
>>>          Add an additional patch to fix ExitBootServices.
>>>          Provide comments for EFI block driver.
>>>          Avoid printing when not in debug mode
>>>          Add product tools/file2include to .gitignore.
>>>          Put the patch with the test for block io after the patch for the
>>>          driver.
>>>
>>> Heinrich Schuchardt (18):
>>>    efi_loader: return NULL from device path functions
>>>    efi_loader: address of the simple file system protocol
>>>    efi_loader: correct find simple file system protocol
>>>    efi_loader: print device path when entering efi_load_image
>>>    efi_loader: allocate correct memory type for EFI image
>>>    efi_loader: check tables in helloworld.efi
>>>    efi_loader: fix StartImage bootservice
>>>    efi_loader: efi_disk_register: correctly determine if_type_name
>>>    efi_loader: make efi_block_io_guid a global symbol
>>>    efi_loader: provide a function to create a partition node
>>>    efi_loader: make efi_disk_create_partitions a global symbol
>>>    efi_loader: correct EFI_BLOCK_IO_PROTOCOL definitions
>>>    efi_loader: provide function to get last node of a device path
>>>    efi_loader: provide links between devices EFI handles
>>>    tools: provide a tool to convert a binary file to an include
>>>    efi_driver: EFI block driver
>>>    efi_selftest: provide a test for block io
>>>    efi_loader: fix ExitBootServices
>>>
>>>   MAINTAINERS                                  |   1 +
>>>   common/board_r.c                             |   3 +
>>>   drivers/block/blk-uclass.c                   |   4 +-
>>>   include/blk.h                                |   1 +
>>>   include/config_fallbacks.h                   |   1 +
>>>   include/dm/device.h                          |   4 +
>>>   include/dm/uclass-id.h                       |   1 +
>>>   include/efi_api.h                            |  16 +-
>>>   include/efi_driver.h                         |  30 ++
>>>   include/efi_loader.h                         |  21 +-
>>>   lib/Makefile                                 |   1 +
>>>   lib/efi_driver/Makefile                      |  13 +
>>>   lib/efi_driver/efi_block_device.c            | 175 ++++++++++++
>>>   lib/efi_driver/efi_uclass.c                  | 330
>>> ++++++++++++++++++++++
>>>   lib/efi_loader/efi_boottime.c                |  42 ++-
>>>   lib/efi_loader/efi_device_path.c             | 168 +++++++++---
>>>   lib/efi_loader/efi_disk.c                    | 137 +++++++---
>>>   lib/efi_loader/efi_image_loader.c            |  64 +++--
>>>   lib/efi_loader/helloworld.c                  |  26 ++
>>>   lib/efi_selftest/Makefile                    |   4 +
>>>   lib/efi_selftest/efi_selftest_block_device.c | 395
>>> +++++++++++++++++++++++++++
>>>   lib/efi_selftest/efi_selftest_disk_image.h   |  69 +++++
>>>   tools/.gitignore                             |   1 +
>>>   tools/Makefile                               |   3 +
>>>   tools/file2include.c                         | 106 +++++++
>>>   25 files changed, 1493 insertions(+), 123 deletions(-)
>>>   create mode 100644 include/efi_driver.h
>>>   create mode 100644 lib/efi_driver/Makefile
>>>   create mode 100644 lib/efi_driver/efi_block_device.c
>>>   create mode 100644 lib/efi_driver/efi_uclass.c
>>>   create mode 100644 lib/efi_selftest/efi_selftest_block_device.c
>>>   create mode 100644 lib/efi_selftest/efi_selftest_disk_image.h
>>>   create mode 100644 tools/file2include.c
>>>
>>> --
>>> 2.14.2
>>>
>>
>> Do you have a git tree with these patches? I get errors when applying
>> them.
>
>
> https://github.com/xypron2/u-boot.git
> branch efi-2018-03-rc1
>
>>
>> Some general comments for discussion, based on my limited understanding.
>>
>> At present from what I can tell, this looks through the UCLASS_EFI
>> drivers and instantiates a EFI driver/device for each. But it does not
>> seem to relate this to the U-Boot driver. It seems in fact to create a
>> new device. For example efi_bl_bind() calls blk_create_device().
>
>
> It is important to understand the sequence of events:
>
> U-Boot creates the EFI uclass.
> This uclass iterates over all EFI drivers (only one up to now).
> For each driver it creates a handle.
> on the handle it install the EFI_DRIVER_BINDING protocol.
> U-Boot loads iPXE.
> iPXE creates connects to a target on an iSCSI server
>
> Up to this point the iSCSI drive that we want to connect to as a block
> device is completely unknown to U-Boot.

This seems wonky to me. If U-Boot is hosting a device it should at
least know about it. We should not have a parallel system with its own
devices - it will get horribly confusing.

Is it not possible to create a device within the U-Boot driver model,
with an EFI device connecting to it?

>
> iPXE creates a handle for the target and installs the EFI_BLOCK_IO_PROTOCOL
> on the handle.
> iPXE calls ConnectController for this handle (which is referred to as
> controller).
> efi_connect_controller() loops over all handles implementing the
> EFI_DRIVER_BINDING protocol and calls the supported() method of the protocol
> to identify a driver supporting the controller.
> For each driver supporting the controller the start() method is called.
>
> The supported() and start() methods are implemented in the EFI uclass.
> In the supported() and start() methods the protocol GUID exposed by the EFI
> driver is compared to the GUIDS of the protocols installed on the controller
> to find a match.
> If a match is found the EFI uclass calls the bind function of the EFI
> driver.
>
> The EFI block driver now creates a block device.
> For the block device it creates partitions.
> On the partitions it installs the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL.
> The EFI block driver has a read (efi_bl_read) and a write (efi_bl_write)
> function.
> These delegate reads and writes to the EFI_BLOCK_IO_PROTOCOL.
>
> Now iPXE tries to load grub.
> It calls the OpenVolume method of the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL of the
> partition to get an instance of the EFI_FILE_PROTOCOL.
> iPXE calls the Open method of the EFI_FILE_PROTOCOL with the path to grub.
> This method is implemented in efi_file_open().
> efi_file_open calls fs_exists() which calls ext4fs_exitsts() which calls the
> read method of the block device created by the EFI block driver. This method
> is implemented in efi_bl_read().
> efi_bl_read() calls the read_blocks() method of the EFI_BLOCK_IO_PROTOCOL
> exposed by iPXE.
> iPXE now uses the iSCSI protocol to read the requested blocks from the iSCSI
> server.

So are you saying that EFI discovers the device, and then creates a
block device within U-Boot? What is the parent of the block device?

>
>
>>
>> Instead I think there should be a real driver-rmodel device creasted
>> with UCLASS_EFI. It should be a child of the DM UCLASS_BLK device. The
>> could work in a similar way to now, except that it can scan DM devices
>> of a particular UCLASS rather than scanning DM drivers.
>>
>
> There is nothing to scan before the EFI application is running.
> The starting point is ConnectController being called by the EFI application
>
> The EFI uclass is not specific to block devices. It is responsible for all
> future EFI drivers. These could support any kind of virtual devices, e.g. a
> network interface.

Yes, I understand that.

But I think if EFI discovers a device, it should bind it in DM, then
attach an EFI device to that device if needed.

>
>> Also the patch that creates a tool to generate a binary as a header
>> file - can we use the same method as we use for other embedding? See
>> for example how .dtb is done.
>
>
> I avoid embedding a 64kiB disk image. My include results in 728 bytes in the
> binary. I really want compression here.
>
> With further patches I have to include binaries again which compress nicely.

Are you saying that you want to compress the disk image and compile it
into U-Boot? What does that have to do with the .dtb method? It should
not be hard to embedded a compressed image that way, too.

Regards,
Simon