Can DXE drivers be included in executable EFI binary?


joseph@...
 

Hello,

Some computers (what I checked was an LG laptop) do not recognize the NVMe SSD as a block device in the EFI program.
Of course, the OS on the NVMe SSD is bootable.
But when I boot with Shellx64.efi in USB flash memory I can't find that disk.
In this case, load NvmExpressDxe and will be able to find the SSD.

So, I want to include NvmExpressDxe in my executable EFI Binary.
Or, after making the multiple files into FV, can make the FV into an executable EFI file?

Thanks.


Laszlo Ersek
 

Dropping <joseph@zeronsoftn.com> from the address list, because the RH
SMTP server keeps telling me that the domain for that email address
(i.e., "zeronsoftn.com") is unidentifiable. Comments below.

On 02/21/21 07:55, joseph via groups.io wrote:
Hello,

Some computers (what I checked was an LG laptop) do not recognize the NVMe SSD as a block device in the EFI program.
Of course, the OS on the NVMe SSD is bootable.
But when I boot with Shellx64.efi in USB flash memory I can't find that disk.
In this case, load NvmExpressDxe and will be able to find the SSD.

So, I want to include NvmExpressDxe in my executable EFI Binary.
Or, after making the multiple files into FV, can make the FV into an executable EFI file?
These are really bad ideas.

"MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf" is a UEFI_DRIVER.
It is supposed to stay resident, and to provide various protocol services.

Your program is (AIUI) a UEFI_APPLICATION module. When it exits, it's gone.

This shows that, what you're considering, would fundamentally break the
UEFI driver model.

If your platform does not provide an NVMe driver, consider distributing
an NvmExpressDxe driver binary (in accordance with its license) on the
same USB disk as your own application. Users can load it or start it
manually, or they can create a Driver#### option too, for auto-loading it.

Laszlo


joseph@...
 

Hello Laszlo,

Thanks for your answer.

I looked at this a bit more today.
The cause is not that there is no driver, but it seems that Notify does not work properly for the protocol after installing the driver.

Immediately after booting, the EFI Shell recognizes NVMe devices but not partitions and filesystems.
If run `map -u` after loading anything filesystem driver (e.g. ext4) the NVMe partition and filesystems are recognized.

Do you know why?
And how can I Notify to gEfiSimpleFileSystemProtocolGuid?

Immediately after booting,
GetHandleListByProtocol(&gEfiSimpleFileSystemProtocolGuid);
Has a value of 2.

After installing any filesystem driver, its value will be 3.

Thanks.


Laszlo Ersek
 

On 02/22/21 12:12, joseph via [] wrote:
Hello Laszlo,

Thanks for your answer.

I looked at this a bit more today.
The cause is not that there is no driver, but it seems that Notify does not work properly for the protocol after installing the driver.
I don't understand "installing the driver".

Also, what is "notify" in this context? Do you mean the
RegisterProtocolNotify() boot service? In what context are you trying to
use it?

Immediately after booting, the EFI Shell recognizes NVMe devices but not partitions and filesystems.
If run `map -u` after loading anything filesystem driver (e.g. ext4) the NVMe partition and filesystems are recognized.
The BDS phase is responsible for connecting devices.

BDS is platform policy though. Even if you have a correctly loaded &
functioning NVMe driver, if BDS does not connect NVMe devices for you,
your application will not see them out of the box.

Your application may call ConnectController(). You can use whatever
methods to locate the suitable handles (you can collect PciIo interfaces
and check them for various signs, or you can use LocateDevicePath()
etc). Once you have some candidate handles, you could call
ConnectController().

When you enter the UEFI shell, there's usually a "connect all devices to
all drivers" step. That may be expensive, so it's usually not done for a
normal boot.

Do you know why?
And how can I Notify to gEfiSimpleFileSystemProtocolGuid?
I don't understand this.

Please describe the symptoms better, and also what you're trying to achieve.

Thanks
Laszlo


Immediately after booting,
GetHandleListByProtocol(&gEfiSimpleFileSystemProtocolGuid);
Has a value of 2.

After installing any filesystem driver, its value will be 3.

Thanks.


joseph@...
 

Hello Laszlo,

It has not been checked in detail, but my predictions are this.
1. When a driver is loaded, it calls "InstallMultipleProtocolInterfaces" within that driver.
2. In this process, "CoreNotifyProtocolEntry" is finally called.
I thought this was the cause of the problem solve, so I thought I should "Notify" the filesystem protocol.


The current situation is like this. This is the mapping table in the EFI Shell right after booting:
FS0: ... PciRoot(0x0)/Pci(0x14,0x0)/USB(0x1,0x0)/HD(1,MBR,...)
BLK0: PciRoot(0x0)/Pci(0x14,0x0)/USB(0x1,0x0)
BLK1: PciRoot(0x0)/Pci(0x17,0x0)/Sata(0x0,0x0,0x0)
After `load (anything filesystem driver).efi` and `map -u`:
FS0: ... PciRoot(0x0)/Pci(0x14,0x0)/USB(0x1,0x0)/HD(1,MBR,...)
BLK0: PciRoot(0x0)/Pci(0x14,0x0)/USB(0x1,0x0)
BLK1: PciRoot(0x0)/Pci(0x17,0x0)/Sata(0x0,0x0,0x0)
FS1: PciRoot(0x0)/Pci(0x17,0x0)/Sata(0x0,0x0,0x0)/HD(1,GPT,.....) <= The newly detected one.
Thanks
Joseph.


joseph@...
 

Hello Laszlo,

Thank you sincerely!
It works just as you said!

Snippet: https://gist.github.com/jc-lab/e9c019b8f5c220d06fe312c9bf3af350

Thanks
Jospeh.


Laszlo Ersek
 

On 02/23/21 02:22, joseph via [] wrote:
Hello Laszlo,

It has not been checked in detail, but my predictions are this.
1. When a driver is loaded, it calls "InstallMultipleProtocolInterfaces" within that driver.
This applies only to drivers that do not follow the UEFI Driver Model
(considering the protocols that expose the driver's actual business).

NvmExpressDxe is a UEFI_DRIVER that follows the UEFI Driver Model. In
its entry point (i.e., when it is loaded), it does not install BlockIo.
It installs BlockIo only when it binds PciIo, generally due to some
ConnectController() calls.

2. In this process, "CoreNotifyProtocolEntry" is finally called.
Protocol installations always have to trigger notifications that have
been registered with the RegisterProtocolNotify() boot service, but
RegisterProtocolNotify() is again something that a driver following the
UEFI Driver Model would not use. RegisterProtocolNotify() is generally
used by DXE_DRIVER modules and UEFI_DRIVERs that don't follow the UEFI
Driver Model.

I thought this was the cause of the problem solve, so I thought I should "Notify" the filesystem protocol.


The current situation is like this. This is the mapping table in the EFI Shell right after booting:
FS0: ... PciRoot(0x0)/Pci(0x14,0x0)/USB(0x1,0x0)/HD(1,MBR,...)
BLK0: PciRoot(0x0)/Pci(0x14,0x0)/USB(0x1,0x0)
BLK1: PciRoot(0x0)/Pci(0x17,0x0)/Sata(0x0,0x0,0x0)
After `load (anything filesystem driver).efi` and `map -u`:
FS0: ... PciRoot(0x0)/Pci(0x14,0x0)/USB(0x1,0x0)/HD(1,MBR,...)
BLK0: PciRoot(0x0)/Pci(0x14,0x0)/USB(0x1,0x0)
BLK1: PciRoot(0x0)/Pci(0x17,0x0)/Sata(0x0,0x0,0x0)
FS1: PciRoot(0x0)/Pci(0x17,0x0)/Sata(0x0,0x0,0x0)/HD(1,GPT,.....) <= The newly detected one.
Please see the shell spec on the "load" command:

This command loads an driver into memory. It can load multiple files
at one time, and the file name supports wildcards.

If the -nc flag is not specified, this command will try to connect
the driver to a proper device; it may also cause already loaded
drivers be connected to their corresponding devices.

So my impression is that your BDS might not connect the partition driver
(PartitionDxe) to the SATA disk's BlockIo / DiskIo protocol interfaces
[*]. But when you load a filesystem driver, even that kind of connection
could be made.

[*] see e.g. commit b82802b83f069 for the SATA-related protocol stack,
up to and including BlockIo

Laszlo


joseph@...
 

It was very helpful.
Thank you for your kindness!