|
|
a85e8e |
From 0faa80b06bc1e9956d7ee6aa3b23574b7c4c18c8 Mon Sep 17 00:00:00 2001
|
|
|
a85e8e |
From: Andrei Borzenkov <arvidjaar@gmail.com>
|
|
|
a85e8e |
Date: Thu, 7 May 2015 20:37:17 +0300
|
|
|
a85e8e |
Subject: [PATCH 162/260] efinet: skip virtual IPv4 and IPv6 devices when
|
|
|
a85e8e |
enumerating cards
|
|
|
a85e8e |
|
|
|
a85e8e |
EDK2 PXE driver creates two child devices - IPv4 and IPv6 - with
|
|
|
a85e8e |
bound SNP instance. This means we get three cards for every physical
|
|
|
a85e8e |
adapter when enumerating. Not only is this confusing, this may result
|
|
|
a85e8e |
in grub ignoring packets that come in via the "wrong" card.
|
|
|
a85e8e |
|
|
|
a85e8e |
Example of device hierarchy is
|
|
|
a85e8e |
|
|
|
a85e8e |
Ctrl[91] PciRoot(0x0)/Pci(0x3,0x0)
|
|
|
a85e8e |
Ctrl[95] PciRoot(0x0)/Pci(0x3,0x0)/MAC(525400123456,0x1)
|
|
|
a85e8e |
Ctrl[B4] PciRoot(0x0)/Pci(0x3,0x0)/MAC(525400123456,0x1)/IPv4(0.0.0.0)
|
|
|
a85e8e |
Ctrl[BC] PciRoot(0x0)/Pci(0x3,0x0)/MAC(525400123456,0x1)/IPv6(0000:0000:0000:0000:0000:0000:0000:0000)
|
|
|
a85e8e |
|
|
|
a85e8e |
Skip PXE created virtual devices when enumerating cards. Make sure to
|
|
|
a85e8e |
find real card when applying initial autoconfiguration during PXE boot,
|
|
|
a85e8e |
this information is associated with one of child devices.
|
|
|
a85e8e |
---
|
|
|
a85e8e |
grub-core/net/drivers/efi/efinet.c | 51 +++++++++++++++++++++++++++++++++++++-
|
|
|
a85e8e |
1 file changed, 50 insertions(+), 1 deletion(-)
|
|
|
a85e8e |
|
|
|
a85e8e |
diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
|
|
|
a85e8e |
index 78df215be..caa7b5022 100644
|
|
|
a85e8e |
--- a/grub-core/net/drivers/efi/efinet.c
|
|
|
a85e8e |
+++ b/grub-core/net/drivers/efi/efinet.c
|
|
|
a85e8e |
@@ -174,6 +174,29 @@ grub_efinet_findcards (void)
|
|
|
a85e8e |
{
|
|
|
a85e8e |
grub_efi_simple_network_t *net;
|
|
|
a85e8e |
struct grub_net_card *card;
|
|
|
a85e8e |
+ grub_efi_device_path_t *dp, *parent = NULL, *child = NULL;
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ /* EDK2 UEFI PXE driver creates IPv4 and IPv6 messaging devices as
|
|
|
a85e8e |
+ children of main MAC messaging device. We only need one device with
|
|
|
a85e8e |
+ bound SNP per physical card, otherwise they compete with each other
|
|
|
a85e8e |
+ when polling for incoming packets.
|
|
|
a85e8e |
+ */
|
|
|
a85e8e |
+ dp = grub_efi_get_device_path (*handle);
|
|
|
a85e8e |
+ if (!dp)
|
|
|
a85e8e |
+ continue;
|
|
|
a85e8e |
+ for (; ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp); dp = GRUB_EFI_NEXT_DEVICE_PATH (dp))
|
|
|
a85e8e |
+ {
|
|
|
a85e8e |
+ parent = child;
|
|
|
a85e8e |
+ child = dp;
|
|
|
a85e8e |
+ }
|
|
|
a85e8e |
+ if (child
|
|
|
a85e8e |
+ && GRUB_EFI_DEVICE_PATH_TYPE (child) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
|
|
|
a85e8e |
+ && (GRUB_EFI_DEVICE_PATH_SUBTYPE (child) == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
|
|
|
a85e8e |
+ || GRUB_EFI_DEVICE_PATH_SUBTYPE (child) == GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE)
|
|
|
a85e8e |
+ && parent
|
|
|
a85e8e |
+ && GRUB_EFI_DEVICE_PATH_TYPE (parent) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
|
|
|
a85e8e |
+ && GRUB_EFI_DEVICE_PATH_SUBTYPE (parent) == GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE)
|
|
|
a85e8e |
+ continue;
|
|
|
a85e8e |
|
|
|
a85e8e |
net = grub_efi_open_protocol (*handle, &net_io_guid,
|
|
|
a85e8e |
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
|
|
a85e8e |
@@ -252,7 +275,33 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
|
|
|
a85e8e |
if (! cdp)
|
|
|
a85e8e |
continue;
|
|
|
a85e8e |
if (grub_efi_compare_device_paths (dp, cdp) != 0)
|
|
|
a85e8e |
- continue;
|
|
|
a85e8e |
+ {
|
|
|
a85e8e |
+ grub_efi_device_path_t *ldp, *dup_dp, *dup_ldp;
|
|
|
a85e8e |
+ int match;
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ /* EDK2 UEFI PXE driver creates pseudo devices with type IPv4/IPv6
|
|
|
a85e8e |
+ as children of Ethernet card and binds PXE and Load File protocols
|
|
|
a85e8e |
+ to it. Loaded Image Device Path protocol will point to these pseudo
|
|
|
a85e8e |
+ devices. We skip them when enumerating cards, so here we need to
|
|
|
a85e8e |
+ find matching MAC device.
|
|
|
a85e8e |
+ */
|
|
|
a85e8e |
+ ldp = grub_efi_find_last_device_path (dp);
|
|
|
a85e8e |
+ if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
|
|
|
a85e8e |
+ || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
|
|
|
a85e8e |
+ && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE))
|
|
|
a85e8e |
+ continue;
|
|
|
a85e8e |
+ dup_dp = grub_efi_duplicate_device_path (dp);
|
|
|
a85e8e |
+ if (!dup_dp)
|
|
|
a85e8e |
+ continue;
|
|
|
a85e8e |
+ dup_ldp = grub_efi_find_last_device_path (dup_dp);
|
|
|
a85e8e |
+ dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
|
|
|
a85e8e |
+ dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
|
|
|
a85e8e |
+ dup_ldp->length = sizeof (*dup_ldp);
|
|
|
a85e8e |
+ match = grub_efi_compare_device_paths (dup_dp, cdp) == 0;
|
|
|
a85e8e |
+ grub_free (dup_dp);
|
|
|
a85e8e |
+ if (!match)
|
|
|
a85e8e |
+ continue;
|
|
|
a85e8e |
+ }
|
|
|
a85e8e |
pxe = grub_efi_open_protocol (hnd, &pxe_io_guid,
|
|
|
a85e8e |
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
|
|
a85e8e |
if (! pxe)
|
|
|
a85e8e |
--
|
|
|
a85e8e |
2.13.0
|
|
|
a85e8e |
|