diff mbox series

[RFC] lib: efi_loader: don't delete invalid handles

Message ID 20220907082013.66879-1-etienne.carriere@linaro.org
State New
Headers show
Series [RFC] lib: efi_loader: don't delete invalid handles | expand

Commit Message

Etienne Carriere Sept. 7, 2022, 8:20 a.m. UTC
Changes efi_delete_handle() to not free EFI handles that are not related
to EFI objects.

This change tries to resolved an issue seen since U-Boot v2022.07
in which EFI ExitBootService  attempts to release some EFI handles twice.

The issue was seen booting a EFI shell that invokes 'connect -r' and
then boots a Linux kernel. Execution of connect command makes EFI
subsystem to bind a block device for each root block devices EFI handles.
However these EFI device handles are already bound to a driver and we
can have 2 registered devices relating to the same EFI handler. On
ExitBootService, the loop removing the devices makes these EFI handles
to be released twice which corrupts memory.

This patch prevents the memory release operation caused by the issue but
I don't think this patch is the right way to addresse the problem. Any
help will be much appreciated.

Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
---
 lib/efi_loader/efi_boottime.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

Comments

Simon Glass Sept. 7, 2022, 9:10 p.m. UTC | #1
Hi Etienne,

On Wed, 7 Sept 2022 at 02:20, Etienne Carriere
<etienne.carriere@linaro.org> wrote:
>
> Changes efi_delete_handle() to not free EFI handles that are not related
> to EFI objects.
>
> This change tries to resolved an issue seen since U-Boot v2022.07
> in which EFI ExitBootService  attempts to release some EFI handles twice.
>
> The issue was seen booting a EFI shell that invokes 'connect -r' and
> then boots a Linux kernel. Execution of connect command makes EFI
> subsystem to bind a block device for each root block devices EFI handles.
> However these EFI device handles are already bound to a driver and we
> can have 2 registered devices relating to the same EFI handler. On
> ExitBootService, the loop removing the devices makes these EFI handles
> to be released twice which corrupts memory.
>
> This patch prevents the memory release operation caused by the issue but
> I don't think this patch is the right way to addresse the problem. Any
> help will be much appreciated.
>
> Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
> ---
>  lib/efi_loader/efi_boottime.c | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)

+AKASHI Takahiro who has been working on resolving the mismatch
between driver model and the EFI implementation. We should be able to
attach EFI data structures to driver model devices, which may help
with this issue.

What is the next step, there?

Regards,
Simon
AKASHI Takahiro Sept. 8, 2022, 5:17 a.m. UTC | #2
On Wed, Sep 07, 2022 at 03:10:44PM -0600, Simon Glass wrote:
> Hi Etienne,
> 
> On Wed, 7 Sept 2022 at 02:20, Etienne Carriere
> <etienne.carriere@linaro.org> wrote:
> >
> > Changes efi_delete_handle() to not free EFI handles that are not related
> > to EFI objects.
> >
> > This change tries to resolved an issue seen since U-Boot v2022.07
> > in which EFI ExitBootService  attempts to release some EFI handles twice.
> >
> > The issue was seen booting a EFI shell that invokes 'connect -r' and
> > then boots a Linux kernel. Execution of connect command makes EFI
> > subsystem to bind a block device for each root block devices EFI handles.
> > However these EFI device handles are already bound to a driver and we
> > can have 2 registered devices relating to the same EFI handler. On
> > ExitBootService, the loop removing the devices makes these EFI handles
> > to be released twice which corrupts memory.
> >
> > This patch prevents the memory release operation caused by the issue but
> > I don't think this patch is the right way to addresse the problem. Any
> > help will be much appreciated.
> >
> > Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
> > ---
> >  lib/efi_loader/efi_boottime.c | 8 +++++++-
> >  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> +AKASHI Takahiro who has been working on resolving the mismatch
> between driver model and the EFI implementation. We should be able to
> attach EFI data structures to driver model devices, which may help
> with this issue.

The only driver which supports DRIVER_BINDING_PROTOCOL, hence
connect_controller() interface, in the current UEFI implementation
is "EFI block driver" (lib/efi_driver/efi_block_device.c).

*Ordinary* block devices, other than UCLASS_EFI_LOADER, are set up
without *binding* step. Nevertheless, "connect -r" eventually
ends up calling "bind" operation of efi_block_device against those
devices.
I guess that it is the root cause.

efi_uc_supported() should have a stricter check.

-Takahiro Akashi


> What is the next step, there?
> 
> Regards,
> Simon
Heinrich Schuchardt Sept. 8, 2022, 5:56 a.m. UTC | #3
On 9/7/22 23:10, Simon Glass wrote:
> Hi Etienne,
>
> On Wed, 7 Sept 2022 at 02:20, Etienne Carriere
> <etienne.carriere@linaro.org> wrote:
>>
>> Changes efi_delete_handle() to not free EFI handles that are not related
>> to EFI objects.
>>
>> This change tries to resolved an issue seen since U-Boot v2022.07
>> in which EFI ExitBootService  attempts to release some EFI handles twice.
>>
>> The issue was seen booting a EFI shell that invokes 'connect -r' and
>> then boots a Linux kernel. Execution of connect command makes EFI
>> subsystem to bind a block device for each root block devices EFI handles.
>> However these EFI device handles are already bound to a driver and we
>> can have 2 registered devices relating to the same EFI handler. On
>> ExitBootService, the loop removing the devices makes these EFI handles
>> to be released twice which corrupts memory.
>>
>> This patch prevents the memory release operation caused by the issue but
>> I don't think this patch is the right way to addresse the problem. Any
>> help will be much appreciated.
>>
>> Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
>> ---
>>   lib/efi_loader/efi_boottime.c | 8 +++++++-
>>   1 file changed, 7 insertions(+), 1 deletion(-)
>
> +AKASHI Takahiro who has been working on resolving the mismatch
> between driver model and the EFI implementation. We should be able to
> attach EFI data structures to driver model devices, which may help
> with this issue.
>
> What is the next step, there?
>
> Regards,
> Simon

One of the bugs is in efi_disk_delete_raw().

The only allowable way to delete a handle is to delete all protocols
that are installed on it. But there are some caveats:

* Protocols may not be removable because they have been opened by a
driver or a child controller.
* We should only remove those protocols that we installed.

A correct DM-EFI interface implementation would do the following:

* When creating a block device create a handle.
* Install the EFI_BLOCK_IO_PROTOCOL on it.
* Use ConnectController() to install all other protocols on it. Our
implementation of the binding protocol then must open the
EFI_BLOCK_IO_PROTOCOL with EFI_OPEN_PROTOCOL_BY_DRIVER.
* When trying to remove the block device call
UninstallProtocolInterface() for the EFI_BLOCK_IO_PROTOCOL. This invokes
DisconnectController() for all drivers that have opened the protocol
with EFI_OPEN_PROTOCOL_BY_DRIVER. Only if uninstalling the protocol
interface succeeds remove the block device.

To make this all work we have to change efi_bl_bind(). We have to
differentiate here between a handle being passed in from outside
(IF_EFI_LOADER) and a handle for a U-Boot device. We should be able to
do so using the field dev in efi_object. If it is NULL, the handle is
not for a U-Boot device.

Further we need to implement the missing unbind function in the
efi_block driver.

The ConnectController() call has to be in efi_disk_probe().
The UninstallProtocolInterface() call has to be in efi_disk_remove().

Enough work for the next release cycle.

Best regards

Heinrich
Heinrich Schuchardt Sept. 8, 2022, 6:03 a.m. UTC | #4
On 9/7/22 10:20, Etienne Carriere wrote:
> Changes efi_delete_handle() to not free EFI handles that are not related
> to EFI objects.
>
> This change tries to resolved an issue seen since U-Boot v2022.07
> in which EFI ExitBootService  attempts to release some EFI handles twice.
>
> The issue was seen booting a EFI shell that invokes 'connect -r' and
> then boots a Linux kernel. Execution of connect command makes EFI
> subsystem to bind a block device for each root block devices EFI handles.
> However these EFI device handles are already bound to a driver and we
> can have 2 registered devices relating to the same EFI handler. On
> ExitBootService, the loop removing the devices makes these EFI handles
> to be released twice which corrupts memory.
>
> This patch prevents the memory release operation caused by the issue but
> I don't think this patch is the right way to addresse the problem. Any
> help will be much appreciated.
>
> Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
> ---
>   lib/efi_loader/efi_boottime.c | 8 +++++++-
>   1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
> index 4da64b5d29..e38990ace2 100644
> --- a/lib/efi_loader/efi_boottime.c
> +++ b/lib/efi_loader/efi_boottime.c
> @@ -619,9 +619,15 @@ efi_status_t efi_remove_all_protocols(const efi_handle_t handle)
>    */
>   void efi_delete_handle(efi_handle_t handle)
>   {
> +	efi_status_t ret;
> +
>   	if (!handle)
>   		return;

The patch does not solve the underlying problem but checking the
validity of the handle makes sense anyway as we have a lot of callers.

We can remove this check as we test the return value of
efi_remove_all_protocols().

> -	efi_remove_all_protocols(handle);
> +
> +	ret = efi_remove_all_protocols(handle);
> +	if (ret == EFI_INVALID_PARAMETER)

We should write a message here.

log_err("Can't remove invalid handle %p\n", handle);

Best regards

Heinrich

> +		return;
> +
>   	list_del(&handle->link);
>   	free(handle);
>   }
Etienne Carriere Sept. 8, 2022, 10:10 a.m. UTC | #5
Hello Heinrich,

Thanks a lot for the detailed feedback on how to address root issue. Indeed
not an obvious fix.

Regards,
Etienne



On Thu, 8 Sept 2022 at 08:03, Heinrich Schuchardt <xypron.glpk@gmx.de>
wrote:

> On 9/7/22 10:20, Etienne Carriere wrote:
> > Changes efi_delete_handle() to not free EFI handles that are not related
> > to EFI objects.
> >
> > This change tries to resolved an issue seen since U-Boot v2022.07
> > in which EFI ExitBootService  attempts to release some EFI handles twice.
> >
> > The issue was seen booting a EFI shell that invokes 'connect -r' and
> > then boots a Linux kernel. Execution of connect command makes EFI
> > subsystem to bind a block device for each root block devices EFI handles.
> > However these EFI device handles are already bound to a driver and we
> > can have 2 registered devices relating to the same EFI handler. On
> > ExitBootService, the loop removing the devices makes these EFI handles
> > to be released twice which corrupts memory.
> >
> > This patch prevents the memory release operation caused by the issue but
> > I don't think this patch is the right way to addresse the problem. Any
> > help will be much appreciated.
> >
> > Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
> > ---
> >   lib/efi_loader/efi_boottime.c | 8 +++++++-
> >   1 file changed, 7 insertions(+), 1 deletion(-)
> >
> > diff --git a/lib/efi_loader/efi_boottime.c
> b/lib/efi_loader/efi_boottime.c
> > index 4da64b5d29..e38990ace2 100644
> > --- a/lib/efi_loader/efi_boottime.c
> > +++ b/lib/efi_loader/efi_boottime.c
> > @@ -619,9 +619,15 @@ efi_status_t efi_remove_all_protocols(const
> efi_handle_t handle)
> >    */
> >   void efi_delete_handle(efi_handle_t handle)
> >   {
> > +     efi_status_t ret;
> > +
> >       if (!handle)
> >               return;
>
> The patch does not solve the underlying problem but checking the
> validity of the handle makes sense anyway as we have a lot of callers.
>
> We can remove this check as we test the return value of
> efi_remove_all_protocols().
>
> > -     efi_remove_all_protocols(handle);
> > +
> > +     ret = efi_remove_all_protocols(handle);
> > +     if (ret == EFI_INVALID_PARAMETER)
>
> We should write a message here.
>
> log_err("Can't remove invalid handle %p\n", handle);
>
> Best regards
>
> Heinrich
>
> > +             return;
> > +
> >       list_del(&handle->link);
> >       free(handle);
> >   }
>
>
Heinrich Schuchardt Sept. 9, 2022, 6:49 a.m. UTC | #6
On 9/8/22 07:56, Heinrich Schuchardt wrote:
> On 9/7/22 23:10, Simon Glass wrote:
>> Hi Etienne,
>>
>> On Wed, 7 Sept 2022 at 02:20, Etienne Carriere
>> <etienne.carriere@linaro.org> wrote:
>>>
>>> Changes efi_delete_handle() to not free EFI handles that are not related
>>> to EFI objects.
>>>
>>> This change tries to resolved an issue seen since U-Boot v2022.07
>>> in which EFI ExitBootService  attempts to release some EFI handles
>>> twice.
>>>
>>> The issue was seen booting a EFI shell that invokes 'connect -r' and
>>> then boots a Linux kernel. Execution of connect command makes EFI
>>> subsystem to bind a block device for each root block devices EFI
>>> handles.
>>> However these EFI device handles are already bound to a driver and we
>>> can have 2 registered devices relating to the same EFI handler. On
>>> ExitBootService, the loop removing the devices makes these EFI handles
>>> to be released twice which corrupts memory.
>>>
>>> This patch prevents the memory release operation caused by the issue but
>>> I don't think this patch is the right way to addresse the problem. Any
>>> help will be much appreciated.
>>>
>>> Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
>>> ---
>>>   lib/efi_loader/efi_boottime.c | 8 +++++++-
>>>   1 file changed, 7 insertions(+), 1 deletion(-)
>>
>> +AKASHI Takahiro who has been working on resolving the mismatch
>> between driver model and the EFI implementation. We should be able to
>> attach EFI data structures to driver model devices, which may help
>> with this issue.
>>
>> What is the next step, there?
>>
>> Regards,
>> Simon
>
> One of the bugs is in efi_disk_delete_raw().
>
> The only allowable way to delete a handle is to delete all protocols
> that are installed on it. But there are some caveats:
>
> * Protocols may not be removable because they have been opened by a
> driver or a child controller.
> * We should only remove those protocols that we installed.
>
> A correct DM-EFI interface implementation would do the following:
>
> * When creating a block device create a handle.
> * Install the EFI_BLOCK_IO_PROTOCOL on it.
> * Use ConnectController() to install all other protocols on it. Our
> implementation of the binding protocol then must open the
> EFI_BLOCK_IO_PROTOCOL with EFI_OPEN_PROTOCOL_BY_DRIVER.
> * When trying to remove the block device call
> UninstallProtocolInterface() for the EFI_BLOCK_IO_PROTOCOL. This invokes
> DisconnectController() for all drivers that have opened the protocol
> with EFI_OPEN_PROTOCOL_BY_DRIVER. Only if uninstalling the protocol
> interface succeeds remove the block device.
>
> To make this all work we have to change efi_bl_bind(). We have to
> differentiate here between a handle being passed in from outside
> (IF_EFI_LOADER) and a handle for a U-Boot device. We should be able to
> do so using the field dev in efi_object. If it is NULL, the handle is
> not for a U-Boot device.
>
> Further we need to implement the missing unbind function in the
> efi_block driver.
>
> The ConnectController() call has to be in efi_disk_probe().
> The UninstallProtocolInterface() call has to be in efi_disk_remove().
>
> Enough work for the next release cycle.
>
> Best regards
>
> Heinrich

The connect -r command calls ConnectController() for all devices.

The only instance of the EFI_DRIVER_BINDING_PROTOCOL that we supply is
for binding to the EFI_BLOCK_IO_PROTOCOL.

In efi_uc_supported() we try to open the the EFI_BLOCK_IO_PROTOCOL with
EFI_OPEN_PROTOCOL_BY_DRIVER. This will return EFI_ALREADY_STARTED if our
driver is already bound to the handle.

This part of the logic works fine and you can see when executing
'connect -r' twice in the EFI Shell.

EFI: Entry efi_uc_supported(000000001b241c40, 000000001b237b60, <NULL>)
   EFI: Call: systab.boottime->open_protocol( controller_handle,
bp->ops->protocol, &interface, this->driver_binding_handle,
controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER)
   EFI: 20 returned by systab.boottime->open_protocol(
controller_handle, bp->ops->protocol, &interface,
this->driver_binding_handle, controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER)
EFI: Exit: efi_uc_supported: 20

Where handle 000000001b237b60 is
/VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(2)

But as we we don't use ConnectController() for installing protocols on
the U-Boot internal devices the driver is not yet bound and EFI_SUCCESS
is returned.

As a short term solution before reworking the design the following
should resolve the reported issue in the UEFI shell:

diff --git a/lib/efi_driver/efi_uclass.c b/lib/efi_driver/efi_uclass.c
index b01ce89c84..d348960fc9 100644
--- a/lib/efi_driver/efi_uclass.c
+++ b/lib/efi_driver/efi_uclass.c
@@ -71,6 +71,11 @@ static efi_status_t EFIAPI efi_uc_supported(
         EFI_ENTRY("%p, %p, %ls", this, controller_handle,
                   efi_dp_str(remaining_device_path));

+       if (controller_handle->dev) {
+               ret = EFI_ALREADY_STARTED;
+               goto out;
+       }
+
         ret = EFI_CALL(systab.boottime->open_protocol(
                         controller_handle, bp->ops->protocol,
                         &interface, this->driver_binding_handle,

Best regards

Heinrich
Etienne Carriere Sept. 9, 2022, 8:46 a.m. UTC | #7
Hello Heinirch,

On Fri, 9 Sept 2022 at 08:55, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
> On 9/8/22 07:56, Heinrich Schuchardt wrote:
> > On 9/7/22 23:10, Simon Glass wrote:
> >> Hi Etienne,
> >>
> >> On Wed, 7 Sept 2022 at 02:20, Etienne Carriere
> >> <etienne.carriere@linaro.org> wrote:
> >>>
> >>> Changes efi_delete_handle() to not free EFI handles that are not related
> >>> to EFI objects.
> >>>
> >>> This change tries to resolved an issue seen since U-Boot v2022.07
> >>> in which EFI ExitBootService  attempts to release some EFI handles
> >>> twice.
> >>>
> >>> The issue was seen booting a EFI shell that invokes 'connect -r' and
> >>> then boots a Linux kernel. Execution of connect command makes EFI
> >>> subsystem to bind a block device for each root block devices EFI
> >>> handles.
> >>> However these EFI device handles are already bound to a driver and we
> >>> can have 2 registered devices relating to the same EFI handler. On
> >>> ExitBootService, the loop removing the devices makes these EFI handles
> >>> to be released twice which corrupts memory.
> >>>
> >>> This patch prevents the memory release operation caused by the issue but
> >>> I don't think this patch is the right way to addresse the problem. Any
> >>> help will be much appreciated.
> >>>
> >>> Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
> >>> ---
> >>>   lib/efi_loader/efi_boottime.c | 8 +++++++-
> >>>   1 file changed, 7 insertions(+), 1 deletion(-)
> >>
> >> +AKASHI Takahiro who has been working on resolving the mismatch
> >> between driver model and the EFI implementation. We should be able to
> >> attach EFI data structures to driver model devices, which may help
> >> with this issue.
> >>
> >> What is the next step, there?
> >>
> >> Regards,
> >> Simon
> >
> > One of the bugs is in efi_disk_delete_raw().
> >
> > The only allowable way to delete a handle is to delete all protocols
> > that are installed on it. But there are some caveats:
> >
> > * Protocols may not be removable because they have been opened by a
> > driver or a child controller.
> > * We should only remove those protocols that we installed.
> >
> > A correct DM-EFI interface implementation would do the following:
> >
> > * When creating a block device create a handle.
> > * Install the EFI_BLOCK_IO_PROTOCOL on it.
> > * Use ConnectController() to install all other protocols on it. Our
> > implementation of the binding protocol then must open the
> > EFI_BLOCK_IO_PROTOCOL with EFI_OPEN_PROTOCOL_BY_DRIVER.
> > * When trying to remove the block device call
> > UninstallProtocolInterface() for the EFI_BLOCK_IO_PROTOCOL. This invokes
> > DisconnectController() for all drivers that have opened the protocol
> > with EFI_OPEN_PROTOCOL_BY_DRIVER. Only if uninstalling the protocol
> > interface succeeds remove the block device.
> >
> > To make this all work we have to change efi_bl_bind(). We have to
> > differentiate here between a handle being passed in from outside
> > (IF_EFI_LOADER) and a handle for a U-Boot device. We should be able to
> > do so using the field dev in efi_object. If it is NULL, the handle is
> > not for a U-Boot device.
> >
> > Further we need to implement the missing unbind function in the
> > efi_block driver.
> >
> > The ConnectController() call has to be in efi_disk_probe().
> > The UninstallProtocolInterface() call has to be in efi_disk_remove().
> >
> > Enough work for the next release cycle.
> >
> > Best regards
> >
> > Heinrich
>
> The connect -r command calls ConnectController() for all devices.
>
> The only instance of the EFI_DRIVER_BINDING_PROTOCOL that we supply is
> for binding to the EFI_BLOCK_IO_PROTOCOL.
>
> In efi_uc_supported() we try to open the the EFI_BLOCK_IO_PROTOCOL with
> EFI_OPEN_PROTOCOL_BY_DRIVER. This will return EFI_ALREADY_STARTED if our
> driver is already bound to the handle.
>
> This part of the logic works fine and you can see when executing
> 'connect -r' twice in the EFI Shell.
>
> EFI: Entry efi_uc_supported(000000001b241c40, 000000001b237b60, <NULL>)
>    EFI: Call: systab.boottime->open_protocol( controller_handle,
> bp->ops->protocol, &interface, this->driver_binding_handle,
> controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER)
>    EFI: 20 returned by systab.boottime->open_protocol(
> controller_handle, bp->ops->protocol, &interface,
> this->driver_binding_handle, controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER)
> EFI: Exit: efi_uc_supported: 20
>
> Where handle 000000001b237b60 is
> /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(2)
>
> But as we we don't use ConnectController() for installing protocols on
> the U-Boot internal devices the driver is not yet bound and EFI_SUCCESS
> is returned.
>
> As a short term solution before reworking the design the following
> should resolve the reported issue in the UEFI shell:
>
> diff --git a/lib/efi_driver/efi_uclass.c b/lib/efi_driver/efi_uclass.c
> index b01ce89c84..d348960fc9 100644
> --- a/lib/efi_driver/efi_uclass.c
> +++ b/lib/efi_driver/efi_uclass.c
> @@ -71,6 +71,11 @@ static efi_status_t EFIAPI efi_uc_supported(
>          EFI_ENTRY("%p, %p, %ls", this, controller_handle,
>                    efi_dp_str(remaining_device_path));
>
> +       if (controller_handle->dev) {
> +               ret = EFI_ALREADY_STARTED;
> +               goto out;
> +       }
> +
>          ret = EFI_CALL(systab.boottime->open_protocol(
>                          controller_handle, bp->ops->protocol,
>                          &interface, this->driver_binding_handle,

Works perfectly, from the few tests I've been through.
Thanks.

>
> Best regards
>
> Heinrich
>
diff mbox series

Patch

diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 4da64b5d29..e38990ace2 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -619,9 +619,15 @@  efi_status_t efi_remove_all_protocols(const efi_handle_t handle)
  */
 void efi_delete_handle(efi_handle_t handle)
 {
+	efi_status_t ret;
+
 	if (!handle)
 		return;
-	efi_remove_all_protocols(handle);
+
+	ret = efi_remove_all_protocols(handle);
+	if (ret == EFI_INVALID_PARAMETER)
+		return;
+
 	list_del(&handle->link);
 	free(handle);
 }