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