View Issue Details

IDProjectCategoryView StatusLast Update
0015307CentOS-7grub2public2018-09-21 20:35
ReporterLiming Sun 
PrioritynormalSeveritymajorReproducibilityalways
Status newResolutionopen 
Product Version7.4.1708 
Target VersionFixed in Version 
Summary0015307: grub2 doesn't support PXE boot over VLAN interface
DescriptionPXE boot over VLAN seems not working. It was found on a ARM SoC board.

The following is what's happening:

UEFI (PXE boot)--> tftp download and execute grubaa64.efi --> grub not able to handle the VLAN interface --> Failed.



Additional Information
A local fix has been made and verified. The fix are uploaded in this bug just for reference. Please feel free to review it or modify it if needed. The changes are based on centos grub repo commit 5405880386df8c709ec2ed2b51fc57103661e5c1.
TagsNo tags attached.
abrt_hash
URL

Activities

Liming Sun

Liming Sun

2018-09-21 20:35

reporter  

v1-0001-efinet-Fix-several-issues-for-VLAN-support.patch (5,062 bytes)
From 00e42c7f4585014798a8b774737d483a2c7d9b73 Mon Sep 17 00:00:00 2001
Message-Id: <00e42c7f4585014798a8b774737d483a2c7d9b73.1537561721.git.lsun@mellanox.com>
From: Liming Sun <lsun@mellanox.com>
Date: Thu, 1 Jan 1970 03:01:46 +0200
Subject: [PATCH v1 1/2] efinet: Fix several issues for VLAN support

This commit has some fixes to support PXE over vlan, which includes

- Parse the EFI boot path to get VLAN information if configured;

- Fix some byte-order related issues in the VLAN support code;

- Fix a race condition and packet-loss issue when VLAN is configured.
  It extends commit fbd83df04b which fixed the same issue but lacking
  VLAN support,

Signed-off-by: Liming Sun <lsun@mellanox.com>
---
 grub-core/net/drivers/efi/efinet.c | 43 ++++++++++++++++++++++++++++++++++++--
 grub-core/net/ethernet.c           |  3 ++-
 include/grub/efi/api.h             |  9 ++++++++
 3 files changed, 52 insertions(+), 3 deletions(-)

diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
index e19dda0..147e1ea 100644
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -22,6 +22,7 @@
 #include <grub/time.h>
 #include <grub/efi/api.h>
 #include <grub/efi/efi.h>
+#include <grub/env.h>
 #include <grub/i18n.h>
 
 GRUB_MOD_LICENSE ("GPLv3+");
@@ -225,8 +226,11 @@ grub_efinet_findcards (void)
 	continue;
       for (; ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp); dp = GRUB_EFI_NEXT_DEVICE_PATH (dp))
 	{
-	  parent = child;
-	  child = dp;
+          if (GRUB_EFI_DEVICE_PATH_SUBTYPE(dp) != GRUB_EFI_VLAN_PATH_SUBTYPE)
+            {
+	      parent = child;
+	      child = dp;
+            }
 	}
       if (child
 	  && GRUB_EFI_DEVICE_PATH_TYPE (child) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
@@ -296,6 +300,32 @@ grub_efinet_findcards (void)
 }
 
 static void
+grub_efi_check_vlan_path (const grub_efi_device_path_t *dp)
+{
+  grub_efi_device_path_t *p;
+
+  for (p = (grub_efi_device_path_t *) dp;
+       ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (p);
+       p = GRUB_EFI_NEXT_DEVICE_PATH (p))
+    {
+      if (p->type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE &&
+          p->subtype == GRUB_EFI_VLAN_PATH_SUBTYPE)
+        {
+          char *buf;
+          grub_efi_vlan_device_path_t *vlan_path;
+
+          vlan_path = (grub_efi_vlan_device_path_t *)p;
+          buf = grub_xasprintf ("0x8100%04x", vlan_path->vlan_id);
+          if (buf)
+            {
+              grub_env_set ("vlan-tag", buf);
+              grub_free (buf);
+            }
+        }
+    }
+}
+
+static void
 grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
 			  char **path)
 {
@@ -339,6 +369,14 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
 	dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
 	dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
 	dup_ldp->length = sizeof (*dup_ldp);
+        /* Skip VLAN. */
+        dup_ldp = grub_efi_find_last_device_path (dup_dp);
+        if (dup_ldp && dup_ldp->type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE &&
+            dup_ldp->subtype == GRUB_EFI_VLAN_PATH_SUBTYPE) {
+	  dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+	  dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+	  dup_ldp->length = sizeof (*dup_ldp);
+        }
 	match = grub_efi_compare_device_paths (dup_dp, cdp) == 0;
 	grub_free (dup_dp);
 	if (!match)
@@ -354,6 +392,7 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
 				    &pxe_mode->dhcp_ack,
 				    sizeof (pxe_mode->dhcp_ack),
 				    1, device, path);
+    grub_efi_check_vlan_path(dp);
     return;
   }
 }
diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c
index faaca67..b861381 100644
--- a/grub-core/net/ethernet.c
+++ b/grub-core/net/ethernet.c
@@ -67,6 +67,7 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf,
   if (vlantag_text != 0) {
       etherhdr_size += 4;
       vlantag = grub_strtoul (vlantag_text, 0, 16);
+      vlantag = grub_cpu_to_be32(vlantag);
   }
 
   err = grub_netbuff_push (nb, etherhdr_size);
@@ -119,7 +120,7 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb,
   grub_memcpy (&vlantag_identifier, nb->data + etherhdr_size - 2, 2);
 
   /* Check if a vlan-tag is present. */
-  if (vlantag_identifier == VLANTAG_IDENTIFIER)
+  if (grub_be_to_cpu16(vlantag_identifier) == VLANTAG_IDENTIFIER)
     {
       etherhdr_size += 4;
       /* Move eth type to the original position */
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index 9dd8307..b57cd3a 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -832,6 +832,15 @@ typedef struct grub_efi_sata_device_path grub_efi_sata_device_path_t;
 
 #define GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE	10
 
+#define GRUB_EFI_VLAN_PATH_SUBTYPE			20
+
+struct grub_efi_vlan_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_uint16_t vlan_id;
+} GRUB_PACKED;
+typedef struct grub_efi_vlan_device_path grub_efi_vlan_device_path_t;
+
 /* Media Device Path.  */
 #define GRUB_EFI_MEDIA_DEVICE_PATH_TYPE			4
 
-- 
1.8.3.1

v1-0002-net-Fix-the-timeout-issue-of-large-tftp-block-siz.patch (1,743 bytes)
From 5b7345ae645442f1b93369fbf3c8e64c1722ee53 Mon Sep 17 00:00:00 2001
Message-Id: <5b7345ae645442f1b93369fbf3c8e64c1722ee53.1537561722.git.lsun@mellanox.com>
In-Reply-To: <00e42c7f4585014798a8b774737d483a2c7d9b73.1537561721.git.lsun@mellanox.com>
References: <00e42c7f4585014798a8b774737d483a2c7d9b73.1537561721.git.lsun@mellanox.com>
From: Liming Sun <lsun@mellanox.com>
Date: Sat, 23 Jun 2018 18:08:12 +0300
Subject: [PATCH v1 2/2] net: Fix the timeout issue of large tftp block-size

---
 grub-core/net/ip.c   | 4 ++--
 grub-core/net/tftp.c | 6 +++---
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c
index c6971f9..1761d60 100644
--- a/grub-core/net/ip.c
+++ b/grub-core/net/ip.c
@@ -360,10 +360,10 @@ static void
 free_old_fragments (void)
 {
   struct reassemble *rsm, **prev;
-  grub_uint64_t limit_time = grub_get_time_ms () - 90000;
+  grub_uint64_t limit_time = grub_get_time_ms ();
 
   for (prev = &reassembles, rsm = *prev; rsm; rsm = *prev)
-    if (rsm->last_time < limit_time)
+    if (rsm->last_time + 90000 < limit_time)
       {
 	*prev = rsm->next;
 	free_rsm (rsm);
diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
index 5173614..dd2d058 100644
--- a/grub-core/net/tftp.c
+++ b/grub-core/net/tftp.c
@@ -346,9 +346,9 @@ tftp_open (struct grub_file *file, const char *filename)
   rrqlen += grub_strlen ("blksize") + 1;
   rrq += grub_strlen ("blksize") + 1;
 
-  grub_strcpy (rrq, "1024");
-  rrqlen += grub_strlen ("1024") + 1;
-  rrq += grub_strlen ("1024") + 1;
+  grub_strcpy (rrq, "16000");
+  rrqlen += grub_strlen ("16000") + 1;
+  rrq += grub_strlen ("16000") + 1;
 
   grub_strcpy (rrq, "tsize");
   rrqlen += grub_strlen ("tsize") + 1;
-- 
1.8.3.1

Issue History

Date Modified Username Field Change
2018-09-21 20:35 Liming Sun New Issue
2018-09-21 20:35 Liming Sun File Added: v1-0001-efinet-Fix-several-issues-for-VLAN-support.patch
2018-09-21 20:35 Liming Sun File Added: v1-0002-net-Fix-the-timeout-issue-of-large-tftp-block-siz.patch