nalika / rpms / grub2

Forked from rpms/grub2 2 years ago
Clone

Blame SOURCES/0184-Be-more-aggro-about-actually-using-the-configured-ne.patch

ecb9bb
From 46d5b1ccce248a275b1dcf15824fb3501a32d9dc Mon Sep 17 00:00:00 2001
ecb9bb
From: Peter Jones <pjones@redhat.com>
ecb9bb
Date: Fri, 11 Sep 2015 17:30:49 -0400
ecb9bb
Subject: [PATCH] Be more aggro about actually using the *configured* network
ecb9bb
 device.
ecb9bb
ecb9bb
Right now we use any SNP device with the same mac+IP block, but when
ecb9bb
it's discovered there will be more than one of them.  We need to pick
ecb9bb
the same one we were loaded with, so that  it'll be configured the same
ecb9bb
way as it was before, and won't be re-used by the system firmware later.
ecb9bb
ecb9bb
Resolves: rhbz#1257475
ecb9bb
ecb9bb
Signed-off-by: Peter Jones <example@example.com>
ecb9bb
---
ecb9bb
 grub-core/net/drivers/efi/efinet.c | 124 +++++++++++++++++++++++++++++--------
ecb9bb
 include/grub/efi/api.h             |   4 ++
ecb9bb
 2 files changed, 102 insertions(+), 26 deletions(-)
ecb9bb
ecb9bb
diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
ecb9bb
index c3a128c..fd47b8a 100644
ecb9bb
--- a/grub-core/net/drivers/efi/efinet.c
ecb9bb
+++ b/grub-core/net/drivers/efi/efinet.c
ecb9bb
@@ -239,46 +239,85 @@ grub_efinet_get_device_handle (struct grub_net_card *card)
ecb9bb
   return card->efi_handle;
ecb9bb
 }
ecb9bb
 
ecb9bb
-static void
ecb9bb
-grub_efinet_findcards (void)
ecb9bb
+static int
ecb9bb
+grub_efinet_find_snp_cards (int preferred_only, grub_efi_handle_t preferred,
ecb9bb
+			    int *i)
ecb9bb
 {
ecb9bb
-  grub_efi_uintn_t num_handles;
ecb9bb
-  grub_efi_handle_t *handles;
ecb9bb
+  grub_efi_uintn_t num_handles = 0;
ecb9bb
+  grub_efi_handle_t *handles = NULL;
ecb9bb
   grub_efi_handle_t *handle;
ecb9bb
-  int i = 0;
ecb9bb
+  grub_efi_device_path_t *pdp = NULL, *pp = NULL, *pc = NULL;
ecb9bb
+  int ret = 0;
ecb9bb
+
ecb9bb
+  if (preferred)
ecb9bb
+    {
ecb9bb
+      grub_efi_device_path_t *pdpc;
ecb9bb
+      pdpc = pdp = grub_efi_get_device_path (preferred);
ecb9bb
+      if (pdp == NULL)
ecb9bb
+	{
ecb9bb
+	  grub_print_error ();
ecb9bb
+	  return -1;
ecb9bb
+	}
ecb9bb
 
ecb9bb
-  /* Find handles which support the disk io interface.  */
ecb9bb
+      for (; ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (pdpc);
ecb9bb
+	   pdpc = GRUB_EFI_NEXT_DEVICE_PATH (pdpc))
ecb9bb
+	{
ecb9bb
+	  pp = pc;
ecb9bb
+	  pc = pdpc;
ecb9bb
+	}
ecb9bb
+    }
ecb9bb
+
ecb9bb
+  /* Find handles which support the SNP interface.  */
ecb9bb
   handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &net_io_guid,
ecb9bb
 				    0, &num_handles);
ecb9bb
-  if (! handles)
ecb9bb
-    return;
ecb9bb
-  for (handle = handles; num_handles--; handle++)
ecb9bb
+
ecb9bb
+  for (handle = handles; handle && num_handles--; handle++)
ecb9bb
     {
ecb9bb
       grub_efi_simple_network_t *net;
ecb9bb
       struct grub_net_card *card;
ecb9bb
       grub_efi_device_path_t *dp, *parent = NULL, *child = NULL;
ecb9bb
 
ecb9bb
-      /* EDK2 UEFI PXE driver creates IPv4 and IPv6 messaging devices as
ecb9bb
-	 children of main MAC messaging device. We only need one device with
ecb9bb
-	 bound SNP per physical card, otherwise they compete with each other
ecb9bb
-	 when polling for incoming packets.
ecb9bb
-       */
ecb9bb
+      /* if we're looking for only the preferred handle, skip anything that
ecb9bb
+	 isn't it. */
ecb9bb
+      if (preferred_only && preferred != NULL && *handle != preferred)
ecb9bb
+	continue;
ecb9bb
+
ecb9bb
+      /* if we're not looking for the preferred handle, skip it if it's
ecb9bb
+	 found. */
ecb9bb
+      if (!preferred_only && *handle == preferred)
ecb9bb
+	continue;
ecb9bb
+
ecb9bb
       dp = grub_efi_get_device_path (*handle);
ecb9bb
       if (!dp)
ecb9bb
 	continue;
ecb9bb
-      for (; ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp); dp = GRUB_EFI_NEXT_DEVICE_PATH (dp))
ecb9bb
+
ecb9bb
+      for (; ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp);
ecb9bb
+	   dp = GRUB_EFI_NEXT_DEVICE_PATH (dp))
ecb9bb
 	{
ecb9bb
 	  parent = child;
ecb9bb
 	  child = dp;
ecb9bb
 	}
ecb9bb
-      if (child
ecb9bb
-	  && GRUB_EFI_DEVICE_PATH_TYPE (child) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
ecb9bb
-	  && (GRUB_EFI_DEVICE_PATH_SUBTYPE (child) == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
ecb9bb
-	      || GRUB_EFI_DEVICE_PATH_SUBTYPE (child) == GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE)
ecb9bb
-	  && parent
ecb9bb
-	  && GRUB_EFI_DEVICE_PATH_TYPE (parent) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
ecb9bb
-	  && GRUB_EFI_DEVICE_PATH_SUBTYPE (parent) == GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE)
ecb9bb
-	continue;
ecb9bb
+
ecb9bb
+      if (!preferred_only)
ecb9bb
+	{
ecb9bb
+	  if (pp && pc
ecb9bb
+	      && grub_efi_compare_device_paths (pp, parent) == 0
ecb9bb
+	      && grub_efi_compare_device_paths (pc, child) == 0)
ecb9bb
+	    continue;
ecb9bb
+
ecb9bb
+	  if (child
ecb9bb
+	      && (GRUB_EFI_DEVICE_PATH_IS_TYPE(child,
ecb9bb
+					  GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE,
ecb9bb
+					  GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE) ||
ecb9bb
+		  GRUB_EFI_DEVICE_PATH_IS_TYPE(child,
ecb9bb
+					  GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE,
ecb9bb
+					  GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE))
ecb9bb
+	      && parent
ecb9bb
+	      && (GRUB_EFI_DEVICE_PATH_IS_TYPE(parent,
ecb9bb
+				    GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE,
ecb9bb
+				    GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE)))
ecb9bb
+	    continue;
ecb9bb
+	}
ecb9bb
 
ecb9bb
       net = grub_efi_open_protocol (*handle, &net_io_guid,
ecb9bb
 				    GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
ecb9bb
@@ -302,7 +341,7 @@ grub_efinet_findcards (void)
ecb9bb
 	{
ecb9bb
 	  grub_print_error ();
ecb9bb
 	  grub_free (handles);
ecb9bb
-	  return;
ecb9bb
+	  return -1;
ecb9bb
 	}
ecb9bb
 
ecb9bb
       card->mtu = net->mode->max_packet_size;
ecb9bb
@@ -313,13 +352,14 @@ grub_efinet_findcards (void)
ecb9bb
 	  grub_print_error ();
ecb9bb
 	  grub_free (handles);
ecb9bb
 	  grub_free (card);
ecb9bb
-	  return;
ecb9bb
+	  return -1;
ecb9bb
 	}
ecb9bb
       card->txbusy = 0;
ecb9bb
 
ecb9bb
       card->rcvbufsize = ALIGN_UP (card->mtu, 64) + 256;
ecb9bb
 
ecb9bb
-      card->name = grub_xasprintf ("efinet%d", i++);
ecb9bb
+      card->name = grub_xasprintf ("efinet%d", *i);
ecb9bb
+      *i = (*i)+1;
ecb9bb
       card->driver = &efidriver;
ecb9bb
       card->flags = 0;
ecb9bb
       card->default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
ecb9bb
@@ -330,8 +370,38 @@ grub_efinet_findcards (void)
ecb9bb
       card->efi_handle = *handle;
ecb9bb
 
ecb9bb
       grub_net_card_register (card);
ecb9bb
+      ret++;
ecb9bb
     }
ecb9bb
   grub_free (handles);
ecb9bb
+
ecb9bb
+  return ret;
ecb9bb
+}
ecb9bb
+
ecb9bb
+static void
ecb9bb
+grub_efinet_findcards (void)
ecb9bb
+{
ecb9bb
+  grub_efi_loaded_image_t *image = NULL;
ecb9bb
+  int rc;
ecb9bb
+  int efinet_number = 0;
ecb9bb
+
ecb9bb
+  image = grub_efi_get_loaded_image (grub_efi_image_handle);
ecb9bb
+
ecb9bb
+  if (image && image->device_handle)
ecb9bb
+    {
ecb9bb
+      rc = grub_efinet_find_snp_cards (1, image->device_handle, &efinet_number);
ecb9bb
+      if (rc < 0)
ecb9bb
+	return;
ecb9bb
+
ecb9bb
+      rc = grub_efinet_find_snp_cards (0, image->device_handle, &efinet_number);
ecb9bb
+      if (rc < 0)
ecb9bb
+	return;
ecb9bb
+    }
ecb9bb
+  else
ecb9bb
+    {
ecb9bb
+      rc = grub_efinet_find_snp_cards (0, NULL, &efinet_number);
ecb9bb
+      if (rc < 0)
ecb9bb
+	return;
ecb9bb
+    }
ecb9bb
 }
ecb9bb
 
ecb9bb
 static void
ecb9bb
@@ -353,6 +423,8 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
ecb9bb
     struct grub_efi_pxe_mode *pxe_mode;
ecb9bb
     if (card->driver != &efidriver)
ecb9bb
       continue;
ecb9bb
+    if (hnd != card->efi_handle)
ecb9bb
+      continue;
ecb9bb
     cdp = grub_efi_get_device_path (card->efi_handle);
ecb9bb
     if (! cdp)
ecb9bb
       continue;
ecb9bb
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
ecb9bb
index 029ee92..f0640c2 100644
ecb9bb
--- a/include/grub/efi/api.h
ecb9bb
+++ b/include/grub/efi/api.h
ecb9bb
@@ -573,6 +573,10 @@ typedef struct grub_efi_device_path grub_efi_device_path_t;
ecb9bb
    It seems to be identical to EFI_DEVICE_PATH.  */
ecb9bb
 typedef struct grub_efi_device_path grub_efi_device_path_protocol_t;
ecb9bb
 
ecb9bb
+#define GRUB_EFI_DEVICE_PATH_IS_TYPE(dp, type, subtype) \
ecb9bb
+	((GRUB_EFI_DEVICE_PATH_TYPE(dp) == (type)) && \
ecb9bb
+	 (GRUB_EFI_DEVICE_PATH_SUBTYPE(dp) == (subtype)))
ecb9bb
+
ecb9bb
 #define GRUB_EFI_DEVICE_PATH_TYPE(dp)		((dp)->type & 0x7f)
ecb9bb
 #define GRUB_EFI_DEVICE_PATH_SUBTYPE(dp)	((dp)->subtype)
ecb9bb
 #define GRUB_EFI_DEVICE_PATH_LENGTH(dp)		((dp)->length)
ecb9bb
-- 
ecb9bb
2.4.3
ecb9bb