All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] efinet: correct closing of SNP protocol
@ 2021-10-06  8:30 Heinrich Schuchardt
  2021-10-06  8:30 ` [PATCH 1/2] " Heinrich Schuchardt
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Heinrich Schuchardt @ 2021-10-06  8:30 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Andrei Borzenkov, Vladimir 'phcoder' Serbinenko,
	Nikita Ermakov, Ard Biesheuvel, Atish Patra, Leif Lindholm,
	Andreas Schwab, GRUB development mailing list,
	Heinrich Schuchardt

In the context of the implementation of the EFI_LOAD_FILE2_PROTOCOL for
the initial ramdisk it was observed that opening the SNP protocol failed
(https://lists.gnu.org/archive/html/grub-devel/2021-10/msg00020.html).
This is due to an incorrect call to CloseProtocol().

This is corrected in the first patch.

The second patch provides a new function grub_efi_close_protocol() to
simplify the coding.

Heinrich Schuchardt (2):
  efinet: correct closing of SNP protocol
  efi: library function grub_efi_close_protocol()

 grub-core/kern/efi/efi.c           | 18 ++++++++++++++++++
 grub-core/net/drivers/efi/efinet.c | 30 +++++++++++++++++++++---------
 include/grub/efi/efi.h             |  3 +++
 3 files changed, 42 insertions(+), 9 deletions(-)

-- 
2.32.0



^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/2] efinet: correct closing of SNP protocol
  2021-10-06  8:30 [PATCH 0/2] efinet: correct closing of SNP protocol Heinrich Schuchardt
@ 2021-10-06  8:30 ` Heinrich Schuchardt
  2021-11-23 17:52   ` Daniel Kiper
  2021-10-06  8:30 ` [PATCH 2/2] efi: library function grub_efi_close_protocol() Heinrich Schuchardt
  2021-10-06 14:28 ` [PATCH 0/2] efinet: correct closing of SNP protocol Andreas Schwab
  2 siblings, 1 reply; 6+ messages in thread
From: Heinrich Schuchardt @ 2021-10-06  8:30 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Andrei Borzenkov, Vladimir 'phcoder' Serbinenko,
	Nikita Ermakov, Ard Biesheuvel, Atish Patra, Leif Lindholm,
	Andreas Schwab, GRUB development mailing list,
	Heinrich Schuchardt

In the context of the implementation of the EFI_LOAD_FILE2_PROTOCOL for
the initial ramdisk it was observed that opening the SNP protocol failed.
https://lists.gnu.org/archive/html/grub-devel/2021-10/msg00020.html
This is due to an incorrect call to CloseProtocol().

The first parameter of CloseProtocol() is the handle, not the interface.

We call OpenProtocol() with ControllerHandle = NULL. Hence we must also
call CloseProtcol with ControllerHandel = NULL.

Each call of OpenProtocol() for the same network card handle is expected to
return the same interface pointer. If we want to close the protocol which
we opened non-exclusively when searching for a card, we have to do this
before opening the protocol exclusively.

As there is no guarantee that we successfully open the protocol add checks
in the transmit and receive functions.

Reported-by: Andreas Schwab <schwab@linux-m68k.org>
Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
---
 grub-core/net/drivers/efi/efinet.c | 32 ++++++++++++++++++++++--------
 1 file changed, 24 insertions(+), 8 deletions(-)

diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
index 5388f952b..3f2ff03f5 100644
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -39,6 +39,8 @@ send_card_buffer (struct grub_net_card *dev,
   grub_uint64_t limit_time = grub_get_time_ms () + 4000;
   void *txbuf;
 
+  if (!net)
+    return grub_error (GRUB_ERR_IO, N_("couldn't send network packet"));
   if (dev->txbusy)
     while (1)
       {
@@ -101,6 +103,9 @@ get_card_packet (struct grub_net_card *dev)
   struct grub_net_buff *nb;
   int i;
 
+  if (!net)
+    return NULL;
+
   for (i = 0; i < 2; i++)
     {
       if (!dev->rcvbuf)
@@ -148,11 +153,23 @@ open_card (struct grub_net_card *dev)
 {
   grub_efi_simple_network_t *net;
 
-  /* Try to reopen SNP exlusively to close any active MNP protocol instance
-     that may compete for packet polling
+  if (dev->efi_net)
+    {
+      efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
+		  dev->efi_handle, &net_io_guid,
+		  grub_efi_image_handle, 0);
+      dev->efi_net = NULL;
+    }
+  /*
+   * Try to reopen SNP exlusively to close any active MNP protocol instance
+   * that may compete for packet polling
    */
   net = grub_efi_open_protocol (dev->efi_handle, &net_io_guid,
 				GRUB_EFI_OPEN_PROTOCOL_BY_EXCLUSIVE);
+  /* If exclusively fails, try non-exclusively. */
+  if (!net)
+      net = grub_efi_open_protocol (dev->efi_handle, &net_io_guid,
+				    GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
   if (net)
     {
       if (net->mode->state == GRUB_EFI_NETWORK_STOPPED
@@ -192,13 +209,12 @@ open_card (struct grub_net_card *dev)
 	  efi_call_6 (net->receive_filters, net, filters, 0, 0, 0, NULL);
 	}
 
-      efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
-		  dev->efi_net, &net_io_guid,
-		  grub_efi_image_handle, dev->efi_handle);
       dev->efi_net = net;
+    } else {
+      return grub_error (GRUB_ERR_NET_NO_CARD, "%s: can't open protocol",
+			 dev->name);
     }
 
-  /* If it failed we just try to run as best as we can */
   return GRUB_ERR_NONE;
 }
 
@@ -208,8 +224,8 @@ close_card (struct grub_net_card *dev)
   efi_call_1 (dev->efi_net->shutdown, dev->efi_net);
   efi_call_1 (dev->efi_net->stop, dev->efi_net);
   efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
-	      dev->efi_net, &net_io_guid,
-	      grub_efi_image_handle, dev->efi_handle);
+	      dev->efi_handle, &net_io_guid,
+	      grub_efi_image_handle, 0);
 }
 
 static struct grub_net_card_driver efidriver =
-- 
2.32.0



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/2] efi: library function grub_efi_close_protocol()
  2021-10-06  8:30 [PATCH 0/2] efinet: correct closing of SNP protocol Heinrich Schuchardt
  2021-10-06  8:30 ` [PATCH 1/2] " Heinrich Schuchardt
@ 2021-10-06  8:30 ` Heinrich Schuchardt
  2021-11-23 17:59   ` Daniel Kiper
  2021-10-06 14:28 ` [PATCH 0/2] efinet: correct closing of SNP protocol Andreas Schwab
  2 siblings, 1 reply; 6+ messages in thread
From: Heinrich Schuchardt @ 2021-10-06  8:30 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Andrei Borzenkov, Vladimir 'phcoder' Serbinenko,
	Nikita Ermakov, Ard Biesheuvel, Atish Patra, Leif Lindholm,
	Andreas Schwab, GRUB development mailing list,
	Heinrich Schuchardt

Create a library function for CloseProtocol() and use it for the SNP
driver.

Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
---
 grub-core/kern/efi/efi.c           | 18 ++++++++++++++++++
 grub-core/net/drivers/efi/efinet.c |  8 ++------
 include/grub/efi/efi.h             |  3 +++
 3 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index 8cff7be02..1d331d858 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -117,6 +117,24 @@ grub_efi_open_protocol (grub_efi_handle_t handle,
   return interface;
 }
 
+grub_efi_status_t
+grub_efi_close_protocol (grub_efi_handle_t handle,
+			 grub_efi_guid_t *protocol)
+{
+  grub_efi_boot_services_t *b;
+  grub_efi_status_t status;
+
+
+  b = grub_efi_system_table->boot_services;
+  status = efi_call_4 (b->close_protocol,
+		       handle,
+		       protocol,
+		       grub_efi_image_handle,
+		       0);
+
+  return status;
+}
+
 int
 grub_efi_set_text_mode (int on)
 {
diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
index 3f2ff03f5..2febbf84a 100644
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -155,9 +155,7 @@ open_card (struct grub_net_card *dev)
 
   if (dev->efi_net)
     {
-      efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
-		  dev->efi_handle, &net_io_guid,
-		  grub_efi_image_handle, 0);
+      grub_efi_close_protocol (dev->efi_handle, &net_io_guid);
       dev->efi_net = NULL;
     }
   /*
@@ -223,9 +221,7 @@ close_card (struct grub_net_card *dev)
 {
   efi_call_1 (dev->efi_net->shutdown, dev->efi_net);
   efi_call_1 (dev->efi_net->stop, dev->efi_net);
-  efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
-	      dev->efi_handle, &net_io_guid,
-	      grub_efi_image_handle, 0);
+  grub_efi_close_protocol (dev->efi_handle, &net_io_guid);
 }
 
 static struct grub_net_card_driver efidriver =
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index 83d958f99..12d041f2e 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -35,6 +35,9 @@ EXPORT_FUNC(grub_efi_locate_handle) (grub_efi_locate_search_type_t search_type,
 void *EXPORT_FUNC(grub_efi_open_protocol) (grub_efi_handle_t handle,
 					   grub_efi_guid_t *protocol,
 					   grub_efi_uint32_t attributes);
+grub_efi_status_t
+EXPORT_FUNC(grub_efi_close_protocol) (grub_efi_handle_t handle,
+				      grub_efi_guid_t *protocol);
 int EXPORT_FUNC(grub_efi_set_text_mode) (int on);
 void EXPORT_FUNC(grub_efi_stall) (grub_efi_uintn_t microseconds);
 void *
-- 
2.32.0



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/2] efinet: correct closing of SNP protocol
  2021-10-06  8:30 [PATCH 0/2] efinet: correct closing of SNP protocol Heinrich Schuchardt
  2021-10-06  8:30 ` [PATCH 1/2] " Heinrich Schuchardt
  2021-10-06  8:30 ` [PATCH 2/2] efi: library function grub_efi_close_protocol() Heinrich Schuchardt
@ 2021-10-06 14:28 ` Andreas Schwab
  2 siblings, 0 replies; 6+ messages in thread
From: Andreas Schwab @ 2021-10-06 14:28 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: Daniel Kiper, Andrei Borzenkov,
	Vladimir 'phcoder' Serbinenko, Nikita Ermakov,
	Ard Biesheuvel, Atish Patra, Leif Lindholm,
	GRUB development mailing list

On Okt 06 2021, Heinrich Schuchardt wrote:

> In the context of the implementation of the EFI_LOAD_FILE2_PROTOCOL for
> the initial ramdisk it was observed that opening the SNP protocol failed
> (https://lists.gnu.org/archive/html/grub-devel/2021-10/msg00020.html).
> This is due to an incorrect call to CloseProtocol().
>
> This is corrected in the first patch.
>
> The second patch provides a new function grub_efi_close_protocol() to
> simplify the coding.

Sucessfully tested with
https://download.opensuse.org/ports/riscv/tumbleweed/iso/openSUSE-Tumbleweed-NET-riscv64-Media.iso
on the Hifive Unmatched.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/2] efinet: correct closing of SNP protocol
  2021-10-06  8:30 ` [PATCH 1/2] " Heinrich Schuchardt
@ 2021-11-23 17:52   ` Daniel Kiper
  0 siblings, 0 replies; 6+ messages in thread
From: Daniel Kiper @ 2021-11-23 17:52 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: Andrei Borzenkov, Vladimir 'phcoder' Serbinenko,
	Nikita Ermakov, Ard Biesheuvel, Atish Patra, Leif Lindholm,
	Andreas Schwab, GRUB development mailing list

First of all, sorry for late reply but I am busy...

On Wed, Oct 06, 2021 at 10:30:42AM +0200, Heinrich Schuchardt wrote:
> In the context of the implementation of the EFI_LOAD_FILE2_PROTOCOL for
> the initial ramdisk it was observed that opening the SNP protocol failed.
> https://lists.gnu.org/archive/html/grub-devel/2021-10/msg00020.html
> This is due to an incorrect call to CloseProtocol().
>
> The first parameter of CloseProtocol() is the handle, not the interface.
>
> We call OpenProtocol() with ControllerHandle = NULL. Hence we must also
> call CloseProtcol with ControllerHandel = NULL.
>
> Each call of OpenProtocol() for the same network card handle is expected to
> return the same interface pointer. If we want to close the protocol which
> we opened non-exclusively when searching for a card, we have to do this
> before opening the protocol exclusively.
>
> As there is no guarantee that we successfully open the protocol add checks
> in the transmit and receive functions.
>
> Reported-by: Andreas Schwab <schwab@linux-m68k.org>
> Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
> ---
>  grub-core/net/drivers/efi/efinet.c | 32 ++++++++++++++++++++++--------
>  1 file changed, 24 insertions(+), 8 deletions(-)
>
> diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
> index 5388f952b..3f2ff03f5 100644
> --- a/grub-core/net/drivers/efi/efinet.c
> +++ b/grub-core/net/drivers/efi/efinet.c
> @@ -39,6 +39,8 @@ send_card_buffer (struct grub_net_card *dev,
>    grub_uint64_t limit_time = grub_get_time_ms () + 4000;
>    void *txbuf;
>
> +  if (!net)

if (net == NULL)

> +    return grub_error (GRUB_ERR_IO, N_("couldn't send network packet"));

Could you display more specific error here?

>    if (dev->txbusy)
>      while (1)
>        {
> @@ -101,6 +103,9 @@ get_card_packet (struct grub_net_card *dev)
>    struct grub_net_buff *nb;
>    int i;
>
> +  if (!net)

if (net == NULL)

> +    return NULL;
> +
>    for (i = 0; i < 2; i++)
>      {
>        if (!dev->rcvbuf)
> @@ -148,11 +153,23 @@ open_card (struct grub_net_card *dev)
>  {
>    grub_efi_simple_network_t *net;
>
> -  /* Try to reopen SNP exlusively to close any active MNP protocol instance
> -     that may compete for packet polling
> +  if (dev->efi_net)

if (dev->efi_net != NULL)

... and please fix this in the other places in the patch(es) too...

> +    {
> +      efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
> +		  dev->efi_handle, &net_io_guid,
> +		  grub_efi_image_handle, 0);

s/0/NULL/

> +      dev->efi_net = NULL;
> +    }
> +  /*
> +   * Try to reopen SNP exlusively to close any active MNP protocol instance
> +   * that may compete for packet polling
>     */
>    net = grub_efi_open_protocol (dev->efi_handle, &net_io_guid,
>  				GRUB_EFI_OPEN_PROTOCOL_BY_EXCLUSIVE);
> +  /* If exclusively fails, try non-exclusively. */
> +  if (!net)
> +      net = grub_efi_open_protocol (dev->efi_handle, &net_io_guid,
> +				    GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);

I am not convinced it is correct. Please take a look at send_card_buffer()...

46         st = efi_call_3 (net->get_status, net, 0, &txbuf);
47         if (st != GRUB_EFI_SUCCESS)
48           return grub_error (GRUB_ERR_IO,
49                              N_("couldn't send network packet"));
50         /*
51            Some buggy firmware could return an arbitrary address instead of the
52            txbuf address we trasmitted, so just check that txbuf is non NULL
53            for success.  This is ok because we open the SNP protocol in
54            exclusive mode so we know we're the only ones transmitting on this
    Here ---> ^^^^^^^^^
55            box and since we only transmit one packet at a time we know our
56            transmit was successfull.
57          */
58         if (txbuf)
59           {
60             dev->txbusy = 0;
61             break;
62           }

>    if (net)
>      {
>        if (net->mode->state == GRUB_EFI_NETWORK_STOPPED
> @@ -192,13 +209,12 @@ open_card (struct grub_net_card *dev)
>  	  efi_call_6 (net->receive_filters, net, filters, 0, 0, 0, NULL);
>  	}
>
> -      efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
> -		  dev->efi_net, &net_io_guid,
> -		  grub_efi_image_handle, dev->efi_handle);
>        dev->efi_net = net;
> +    } else {
> +      return grub_error (GRUB_ERR_NET_NO_CARD, "%s: can't open protocol",
> +			 dev->name);
>      }
>
> -  /* If it failed we just try to run as best as we can */
>    return GRUB_ERR_NONE;
>  }
>
> @@ -208,8 +224,8 @@ close_card (struct grub_net_card *dev)
>    efi_call_1 (dev->efi_net->shutdown, dev->efi_net);
>    efi_call_1 (dev->efi_net->stop, dev->efi_net);
>    efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
> -	      dev->efi_net, &net_io_guid,
> -	      grub_efi_image_handle, dev->efi_handle);
> +	      dev->efi_handle, &net_io_guid,
> +	      grub_efi_image_handle, 0);

s/0/NULL/

Daniel


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/2] efi: library function grub_efi_close_protocol()
  2021-10-06  8:30 ` [PATCH 2/2] efi: library function grub_efi_close_protocol() Heinrich Schuchardt
@ 2021-11-23 17:59   ` Daniel Kiper
  0 siblings, 0 replies; 6+ messages in thread
From: Daniel Kiper @ 2021-11-23 17:59 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: Andrei Borzenkov, Vladimir 'phcoder' Serbinenko,
	Nikita Ermakov, Ard Biesheuvel, Atish Patra, Leif Lindholm,
	Andreas Schwab, GRUB development mailing list

On Wed, Oct 06, 2021 at 10:30:43AM +0200, Heinrich Schuchardt wrote:
> Create a library function for CloseProtocol() and use it for the SNP
> driver.
>
> Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
> ---
>  grub-core/kern/efi/efi.c           | 18 ++++++++++++++++++
>  grub-core/net/drivers/efi/efinet.c |  8 ++------
>  include/grub/efi/efi.h             |  3 +++
>  3 files changed, 23 insertions(+), 6 deletions(-)
>
> diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
> index 8cff7be02..1d331d858 100644
> --- a/grub-core/kern/efi/efi.c
> +++ b/grub-core/kern/efi/efi.c
> @@ -117,6 +117,24 @@ grub_efi_open_protocol (grub_efi_handle_t handle,
>    return interface;
>  }
>
> +grub_efi_status_t
> +grub_efi_close_protocol (grub_efi_handle_t handle,
> +			 grub_efi_guid_t *protocol)

grub_efi_close_protocol (grub_efi_handle_t handle, grub_efi_guid_t *protocol)

> +{
> +  grub_efi_boot_services_t *b;
> +  grub_efi_status_t status;
> +
> +

Please drop this redundant empty line...

> +  b = grub_efi_system_table->boot_services;

I think you could do this above:

grub_efi_boot_services_t *b = grub_efi_system_table->boot_services;

> +  status = efi_call_4 (b->close_protocol,
> +		       handle,
> +		       protocol,
> +		       grub_efi_image_handle,
> +		       0);

status = efi_call_4 (b->close_protocol, handle, protocol, grub_efi_image_handle, NULL);

I am OK with lines a bit longer than 80 chars.

Otherwise LGTM.

Daniel


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-11-23 17:59 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-06  8:30 [PATCH 0/2] efinet: correct closing of SNP protocol Heinrich Schuchardt
2021-10-06  8:30 ` [PATCH 1/2] " Heinrich Schuchardt
2021-11-23 17:52   ` Daniel Kiper
2021-10-06  8:30 ` [PATCH 2/2] efi: library function grub_efi_close_protocol() Heinrich Schuchardt
2021-11-23 17:59   ` Daniel Kiper
2021-10-06 14:28 ` [PATCH 0/2] efinet: correct closing of SNP protocol Andreas Schwab

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.