All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/9] Add UEFI HTTP Boot support for IPv4 and IPv6
@ 2016-12-23  8:54 Keng-Yu Lin
  2016-12-23  8:54 ` [PATCH 1/9] strtoull: Fix behaviour on chars between '9' and 'a' Keng-Yu Lin
                   ` (9 more replies)
  0 siblings, 10 replies; 17+ messages in thread
From: Keng-Yu Lin @ 2016-12-23  8:54 UTC (permalink / raw)
  To: grub-devel; +Cc: mchang, ken.lin, ljk, michael.ruan, clayc, kengyu

The patchset is a follow-up to the previous one sent in Auguest.
After talking with Michael Chang, he is happy that we pick up this.

This patchset was tested on a machine with EDK2-derived ROM.
Both ipv4 and ipv6 are tested. The default http port (80) and a
specified port (we chose 79) are also tested. All passed.

See below for more explanation for each patch.

Aaron Miller (1):
  net: read bracketed ipv6 addrs and port numbers

Keng-Yu Lin (1):
  Add default port in grub_net_app_protocol

This one is the main one in reply the last review.
Besides adding the default port grub_net_app_protocol, this patch
also shortened the port string and add a comment to the code for
adding the brackets for un-brackted ipv6 address. The brackets are
required based on the testing result on the real machine.

For port 0, this is not realistic for the real use, because there
is no way for the http server to know in advance which port the
client will get. However, I removed all port 0 checking. From the 
source-level, port 0 should work.

Michael Chang (6):
  bootp: New net_bootp6 command
  efinet: UEFI IPv6 PXE support
  grub.texi: Add net_bootp6 doument
  bootp: Add processing DHCPACK packet from HTTP Boot
  efinet: Setting network from UEFI device path
  efinet: Setting DNS server from UEFI protocol

Vladimir Serbinenko (1):
  strtoull: Fix behaviour on chars between '9' and 'a'.

Dropped Aaron Miller's patch and use this one since it is now in
the grub/next branch. One thing to notice is that the test case
is missing. It causes compiling to fail. We teporarily removed
the test case from grub-core/Makefile.core.def in our testing.


 docs/grub.texi                        |  17 +
 grub-core/Makefile.core.def           |   5 +
 grub-core/kern/misc.c                 |  13 +-
 grub-core/net/bootp.c                 | 975 +++++++++++++++++++++++++++++++++-
 grub-core/net/drivers/efi/efinet.c    | 445 +++++++++++++++-
 grub-core/net/http.c                  |  21 +-
 grub-core/net/ip.c                    |  39 ++
 grub-core/net/net.c                   |  91 +++-
 grub-core/net/tftp.c                  |   9 +-
 grub-core/tests/lib/functional_test.c |  13 +-
 include/grub/efi/api.h                | 142 ++++-
 include/grub/net.h                    |  75 +++
 12 files changed, 1809 insertions(+), 36 deletions(-)

-- 
1.8.3.1



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

* [PATCH 1/9] strtoull: Fix behaviour on chars between '9' and 'a'.
  2016-12-23  8:54 [PATCH v2 0/9] Add UEFI HTTP Boot support for IPv4 and IPv6 Keng-Yu Lin
@ 2016-12-23  8:54 ` Keng-Yu Lin
  2016-12-23  8:54 ` [PATCH 2/9] net: read bracketed ipv6 addrs and port numbers Keng-Yu Lin
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Keng-Yu Lin @ 2016-12-23  8:54 UTC (permalink / raw)
  To: grub-devel
  Cc: mchang, ken.lin, ljk, michael.ruan, clayc, kengyu, Vladimir Serbinenko

From: Vladimir Serbinenko <phcoder@gmail.com>

Reported by: Aaron Miller <aaronmiller@fb.com>
---
 grub-core/Makefile.core.def           |  5 +++++
 grub-core/kern/misc.c                 | 13 +++++++------
 grub-core/tests/lib/functional_test.c | 13 +++++++++++--
 3 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 2dfa22a..8dcd0e5 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1962,6 +1962,11 @@ module = {
 };
 
 module = {
+  name = strtoull_test;
+  common = tests/strtoull_test.c;
+};
+
+module = {
   name = setjmp_test;
   common = tests/setjmp_test.c;
 };
diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
index d1a54df..3b633d5 100644
--- a/grub-core/kern/misc.c
+++ b/grub-core/kern/misc.c
@@ -391,12 +391,13 @@ grub_strtoull (const char *str, char **end, int base)
       unsigned long digit;
 
       digit = grub_tolower (*str) - '0';
-      if (digit > 9)
-	{
-	  digit += '0' - 'a' + 10;
-	  if (digit >= (unsigned long) base)
-	    break;
-	}
+      if (digit >= 'a' - '0')
+	digit += '0' - 'a' + 10;
+      else if (digit > 9)
+	break;
+
+      if (digit >= (unsigned long) base)
+	break;
 
       found = 1;
 
diff --git a/grub-core/tests/lib/functional_test.c b/grub-core/tests/lib/functional_test.c
index d4822a1..96781fb 100644
--- a/grub-core/tests/lib/functional_test.c
+++ b/grub-core/tests/lib/functional_test.c
@@ -26,14 +26,23 @@ GRUB_MOD_LICENSE ("GPLv3+");
 
 static grub_err_t
 grub_functional_test (grub_extcmd_context_t ctxt __attribute__ ((unused)),
-		      int argc __attribute__ ((unused)),
-		      char **args __attribute__ ((unused)))
+		      int argc,
+		      char **args)
 {
   grub_test_t test;
   int ok = 1;
+  int i;
 
   FOR_LIST_ELEMENTS (test, grub_test_list)
     {
+      if (argc != 0)
+	{
+	  for (i = 0; i < argc; i++)
+	    if (grub_strcmp(args[i], test->name) == 0)
+	      break;
+	  if (i == argc)
+	    continue;
+	}
       grub_errno = 0;
       ok = ok && !grub_test_run (test);
       grub_errno = 0;
-- 
2.7.4



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

* [PATCH 2/9] net: read bracketed ipv6 addrs and port numbers
  2016-12-23  8:54 [PATCH v2 0/9] Add UEFI HTTP Boot support for IPv4 and IPv6 Keng-Yu Lin
  2016-12-23  8:54 ` [PATCH 1/9] strtoull: Fix behaviour on chars between '9' and 'a' Keng-Yu Lin
@ 2016-12-23  8:54 ` Keng-Yu Lin
  2016-12-23  8:54 ` [PATCH v2 3/9] Add default port in grub_net_app_protocol Keng-Yu Lin
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Keng-Yu Lin @ 2016-12-23  8:54 UTC (permalink / raw)
  To: grub-devel
  Cc: mchang, ken.lin, ljk, michael.ruan, clayc, kengyu, Aaron Miller

From: Aaron Miller <aaronmiller@fb.com>

Allow specifying port numbers for http and tftp paths, and allow ipv6 addresses
to be recognized with brackets around them, which is required to specify a port
number
---
 grub-core/net/http.c | 21 ++++++++++---
 grub-core/net/net.c  | 86 +++++++++++++++++++++++++++++++++++++++++++++++++---
 grub-core/net/tftp.c |  6 +++-
 include/grub/net.h   |  1 +
 4 files changed, 104 insertions(+), 10 deletions(-)

diff --git a/grub-core/net/http.c b/grub-core/net/http.c
index 5aa4ad3..f182d7b 100644
--- a/grub-core/net/http.c
+++ b/grub-core/net/http.c
@@ -312,12 +312,14 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
   int i;
   struct grub_net_buff *nb;
   grub_err_t err;
+  char* server = file->device->net->server;
+  int port = file->device->net->port;
 
   nb = grub_netbuff_alloc (GRUB_NET_TCP_RESERVE_SIZE
 			   + sizeof ("GET ") - 1
 			   + grub_strlen (data->filename)
 			   + sizeof (" HTTP/1.1\r\nHost: ") - 1
-			   + grub_strlen (file->device->net->server)
+			   + grub_strlen (server) + sizeof (":XXXXXXXXXX")
 			   + sizeof ("\r\nUser-Agent: " PACKAGE_STRING
 				     "\r\n") - 1
 			   + sizeof ("Range: bytes=XXXXXXXXXXXXXXXXXXXX"
@@ -356,7 +358,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
 	       sizeof (" HTTP/1.1\r\nHost: ") - 1);
 
   ptr = nb->tail;
-  err = grub_netbuff_put (nb, grub_strlen (file->device->net->server));
+  err = grub_netbuff_put (nb, grub_strlen (server));
   if (err)
     {
       grub_netbuff_free (nb);
@@ -365,6 +367,15 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
   grub_memcpy (ptr, file->device->net->server,
 	       grub_strlen (file->device->net->server));
 
+  if (port)
+    {
+      ptr = nb->tail;
+      grub_snprintf ((char *) ptr,
+	  sizeof (":XXXXXXXXXX"),
+	  ":%d",
+	  port);
+    }
+
   ptr = nb->tail;
   err = grub_netbuff_put (nb, 
 			  sizeof ("\r\nUser-Agent: " PACKAGE_STRING "\r\n")
@@ -390,8 +401,10 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
   grub_netbuff_put (nb, 2);
   grub_memcpy (ptr, "\r\n", 2);
 
-  data->sock = grub_net_tcp_open (file->device->net->server,
-				  HTTP_PORT, http_receive,
+  grub_dprintf ("http", "opening path %s on host %s TCP port %d\n",
+		data->filename, server, port ? port : HTTP_PORT);
+  data->sock = grub_net_tcp_open (server,
+				  port ? port : HTTP_PORT, http_receive,
 				  http_err, http_err,
 				  file);
   if (!data->sock)
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
index 10773fc..5cc0d2f 100644
--- a/grub-core/net/net.c
+++ b/grub-core/net/net.c
@@ -437,6 +437,12 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest)
   grub_uint16_t newip[8];
   const char *ptr = val;
   int word, quaddot = -1;
+  int bracketed = 0;
+
+  if (ptr[0] == '[') {
+    bracketed = 1;
+    ptr++;
+  }
 
   if (ptr[0] == ':' && ptr[1] != ':')
     return 0;
@@ -475,6 +481,9 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest)
       grub_memset (&newip[quaddot], 0, (7 - word) * sizeof (newip[0]));
     }
   grub_memcpy (ip, newip, 16);
+  if (bracketed && *ptr == ']') {
+    ptr++;
+  }
   if (rest)
     *rest = ptr;
   return 1;
@@ -1260,8 +1269,10 @@ grub_net_open_real (const char *name)
 {
   grub_net_app_level_t proto;
   const char *protname, *server;
+  char *host;
   grub_size_t protnamelen;
   int try;
+  int port = 0;
 
   if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0)
     {
@@ -1299,6 +1310,72 @@ grub_net_open_real (const char *name)
       return NULL;
     }  
 
+  char* port_start;
+  /* ipv6 or port specified? */
+  if ((port_start = grub_strchr (server, ':')))
+  {
+      char* ipv6_begin;
+      if((ipv6_begin = grub_strchr (server, '[')))
+	{
+	  char* ipv6_end = grub_strchr (server, ']');
+	  if(!ipv6_end)
+	    {
+	      grub_error (GRUB_ERR_NET_BAD_ADDRESS,
+		      N_("mismatched [ in address"));
+	      return NULL;
+	    }
+	  /* port number after bracketed ipv6 addr */
+	  if(ipv6_end[1] == ':')
+	    {
+	      port = grub_strtoul (ipv6_end + 2, NULL, 10);
+	      if(port > 65535)
+		{
+		  grub_error (GRUB_ERR_NET_BAD_ADDRESS,
+			  N_("bad port number"));
+		  return NULL;
+		}
+	    }
+	  host = grub_strndup (ipv6_begin, (ipv6_end - ipv6_begin) + 1);
+	}
+      else
+	{
+	  if (grub_strchr (port_start + 1, ':'))
+	    {
+	      int iplen = grub_strlen (server);
+	      /* bracket bare ipv6 addrs */
+	      host = grub_malloc (iplen + 3);
+	      if(!host)
+		{
+		  return NULL;
+		}
+	      host[0] = '[';
+	      grub_memcpy (host + 1, server, iplen);
+	      host[iplen + 1] = ']';
+	      host[iplen + 2] = '\0';
+	    }
+	  else
+	    {
+	      /* hostname:port or ipv4:port */
+	      port = grub_strtol (port_start + 1, NULL, 10);
+	      if(port > 65535)
+		{
+		  grub_error (GRUB_ERR_NET_BAD_ADDRESS,
+			  N_("bad port number"));
+		  return NULL;
+		}
+	      host = grub_strndup (server, port_start - server);
+	    }
+	}
+    }
+  else
+    {
+      host = grub_strdup (server);
+    }
+  if (!host)
+    {
+      return NULL;
+    }
+
   for (try = 0; try < 2; try++)
     {
       FOR_NET_APP_LEVEL (proto)
@@ -1308,14 +1385,13 @@ grub_net_open_real (const char *name)
 	  {
 	    grub_net_t ret = grub_zalloc (sizeof (*ret));
 	    if (!ret)
-	      return NULL;
-	    ret->protocol = proto;
-	    ret->server = grub_strdup (server);
-	    if (!ret->server)
 	      {
-		grub_free (ret);
+		grub_free (host);
 		return NULL;
 	      }
+	    ret->protocol = proto;
+	    ret->port = port;
+	    ret->server = host;
 	    ret->fs = &grub_net_fs;
 	    return ret;
 	  }
diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
index 7d90bf6..a0817a0 100644
--- a/grub-core/net/tftp.c
+++ b/grub-core/net/tftp.c
@@ -314,6 +314,7 @@ tftp_open (struct grub_file *file, const char *filename)
   grub_err_t err;
   grub_uint8_t *nbd;
   grub_net_network_level_address_t addr;
+  int port = file->device->net->port;
 
   data = grub_zalloc (sizeof (*data));
   if (!data)
@@ -382,13 +383,16 @@ tftp_open (struct grub_file *file, const char *filename)
   err = grub_net_resolve_address (file->device->net->server, &addr);
   if (err)
     {
+      grub_dprintf ("tftp", "file_size is %llu, block_size is %llu\n",
+		    (unsigned long long)data->file_size,
+		    (unsigned long long)data->block_size);
       destroy_pq (data);
       grub_free (data);
       return err;
     }
 
   data->sock = grub_net_udp_open (addr,
-				  TFTP_SERVER_PORT, tftp_receive,
+				  port ? port : TFTP_SERVER_PORT, tftp_receive,
 				  file);
   if (!data->sock)
     {
diff --git a/include/grub/net.h b/include/grub/net.h
index 2192fa1..ccc169c 100644
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -270,6 +270,7 @@ typedef struct grub_net
 {
   char *server;
   char *name;
+  int port;
   grub_net_app_level_t protocol;
   grub_net_packets_t packs;
   grub_off_t offset;
-- 
2.7.4



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

* [PATCH v2 3/9] Add default port in grub_net_app_protocol
  2016-12-23  8:54 [PATCH v2 0/9] Add UEFI HTTP Boot support for IPv4 and IPv6 Keng-Yu Lin
  2016-12-23  8:54 ` [PATCH 1/9] strtoull: Fix behaviour on chars between '9' and 'a' Keng-Yu Lin
  2016-12-23  8:54 ` [PATCH 2/9] net: read bracketed ipv6 addrs and port numbers Keng-Yu Lin
@ 2016-12-23  8:54 ` Keng-Yu Lin
  2016-12-23  8:54 ` [PATCH 4/9] bootp: New net_bootp6 command Keng-Yu Lin
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Keng-Yu Lin @ 2016-12-23  8:54 UTC (permalink / raw)
  To: grub-devel; +Cc: mchang, ken.lin, ljk, michael.ruan, clayc, kengyu

In this patch, it introduces port 80 as HTTP's default port,
and port 69 as TFTP's default port.

Signed-off-by: Keng-Yu Lin <kengyu@hpe.com>
---
 grub-core/net/http.c | 22 ++++++----------------
 grub-core/net/net.c  |  7 ++++++-
 grub-core/net/tftp.c |  5 ++++-
 include/grub/net.h   |  1 +
 4 files changed, 17 insertions(+), 18 deletions(-)

diff --git a/grub-core/net/http.c b/grub-core/net/http.c
index f182d7b..08f7580 100644
--- a/grub-core/net/http.c
+++ b/grub-core/net/http.c
@@ -29,11 +29,6 @@
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
-enum
-  {
-    HTTP_PORT = 80
-  };
-
 
 typedef struct http_data
 {
@@ -319,7 +314,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
 			   + sizeof ("GET ") - 1
 			   + grub_strlen (data->filename)
 			   + sizeof (" HTTP/1.1\r\nHost: ") - 1
-			   + grub_strlen (server) + sizeof (":XXXXXXXXXX")
+			   + grub_strlen (server) + sizeof (":XXXXX") /* 0~65535 */
 			   + sizeof ("\r\nUser-Agent: " PACKAGE_STRING
 				     "\r\n") - 1
 			   + sizeof ("Range: bytes=XXXXXXXXXXXXXXXXXXXX"
@@ -367,14 +362,8 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
   grub_memcpy (ptr, file->device->net->server,
 	       grub_strlen (file->device->net->server));
 
-  if (port)
-    {
-      ptr = nb->tail;
-      grub_snprintf ((char *) ptr,
-	  sizeof (":XXXXXXXXXX"),
-	  ":%d",
-	  port);
-    }
+  ptr = nb->tail;
+  grub_snprintf ((char *) ptr, sizeof (":XXXXX"), ":%d", port);
 
   ptr = nb->tail;
   err = grub_netbuff_put (nb, 
@@ -402,9 +391,9 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
   grub_memcpy (ptr, "\r\n", 2);
 
   grub_dprintf ("http", "opening path %s on host %s TCP port %d\n",
-		data->filename, server, port ? port : HTTP_PORT);
+		data->filename, server, port );
   data->sock = grub_net_tcp_open (server,
-				  port ? port : HTTP_PORT, http_receive,
+				  port, http_receive,
 				  http_err, http_err,
 				  file);
   if (!data->sock)
@@ -558,6 +547,7 @@ http_packets_pulled (struct grub_file *file)
 static struct grub_net_app_protocol grub_http_protocol = 
   {
     .name = "http",
+    .default_port = 80,
     .open = http_open,
     .close = http_close,
     .seek = http_seek,
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
index 5cc0d2f..2b329ee 100644
--- a/grub-core/net/net.c
+++ b/grub-core/net/net.c
@@ -1272,7 +1272,7 @@ grub_net_open_real (const char *name)
   char *host;
   grub_size_t protnamelen;
   int try;
-  int port = 0;
+  int port = -1;
 
   if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0)
     {
@@ -1341,6 +1341,10 @@ grub_net_open_real (const char *name)
 	{
 	  if (grub_strchr (port_start + 1, ':'))
 	    {
+	      /* If the second ':' is found and there is no '[' nor ']',
+	         this indicates this is an ipv6 address without brackets.
+	         Bracket the address here.
+	       */
 	      int iplen = grub_strlen (server);
 	      /* bracket bare ipv6 addrs */
 	      host = grub_malloc (iplen + 3);
@@ -1390,6 +1394,7 @@ grub_net_open_real (const char *name)
 		return NULL;
 	      }
 	    ret->protocol = proto;
+	    if (port == -1) port = proto->default_port;
 	    ret->port = port;
 	    ret->server = host;
 	    ret->fs = &grub_net_fs;
diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
index a0817a0..658921b 100644
--- a/grub-core/net/tftp.c
+++ b/grub-core/net/tftp.c
@@ -391,8 +391,10 @@ tftp_open (struct grub_file *file, const char *filename)
       return err;
     }
 
+  grub_dprintf ("tftp","opening host %s UDP port %d\n",
+		    file->device->net->server, port);
   data->sock = grub_net_udp_open (addr,
-				  port ? port : TFTP_SERVER_PORT, tftp_receive,
+				  port, tftp_receive,
 				  file);
   if (!data->sock)
     {
@@ -492,6 +494,7 @@ tftp_packets_pulled (struct grub_file *file)
 static struct grub_net_app_protocol grub_tftp_protocol = 
   {
     .name = "tftp",
+    .default_port = 69,
     .open = tftp_open,
     .close = tftp_close,
     .packets_pulled = tftp_packets_pulled
diff --git a/include/grub/net.h b/include/grub/net.h
index ccc169c..d13ee61 100644
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -257,6 +257,7 @@ struct grub_net_app_protocol
   struct grub_net_app_protocol *next;
   struct grub_net_app_protocol **prev;
   const char *name;
+  int default_port;
   grub_err_t (*dir) (grub_device_t device, const char *path,
 		     int (*hook) (const char *filename,
 				  const struct grub_dirhook_info *info));
-- 
2.7.4



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

* [PATCH 4/9] bootp: New net_bootp6 command
  2016-12-23  8:54 [PATCH v2 0/9] Add UEFI HTTP Boot support for IPv4 and IPv6 Keng-Yu Lin
                   ` (2 preceding siblings ...)
  2016-12-23  8:54 ` [PATCH v2 3/9] Add default port in grub_net_app_protocol Keng-Yu Lin
@ 2016-12-23  8:54 ` Keng-Yu Lin
  2016-12-23  8:54 ` [PATCH 5/9] efinet: UEFI IPv6 PXE support Keng-Yu Lin
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Keng-Yu Lin @ 2016-12-23  8:54 UTC (permalink / raw)
  To: grub-devel; +Cc: mchang, ken.lin, ljk, michael.ruan, clayc, kengyu

From: Michael Chang <mchang@suse.com>

Implement new net_bootp6 command for IPv6 network auto configuration via the
DHCPv6 protocol (RFC3315).

Signed-off-by: Michael Chang <mchang@suse.com>
Signed-off-by: Ken Lin <ken.lin@hpe.com>
---
 grub-core/net/bootp.c | 908 +++++++++++++++++++++++++++++++++++++++++++++++++-
 grub-core/net/ip.c    |  39 +++
 include/grub/net.h    |  72 ++++
 3 files changed, 1018 insertions(+), 1 deletion(-)

diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
index 9e2fdb7..172528e 100644
--- a/grub-core/net/bootp.c
+++ b/grub-core/net/bootp.c
@@ -24,6 +24,98 @@
 #include <grub/net/netbuff.h>
 #include <grub/net/udp.h>
 #include <grub/datetime.h>
+#include <grub/time.h>
+#include <grub/list.h>
+
+static int
+dissect_url (const char *url, char **proto, char **host, char **path)
+{
+  const char *p, *ps;
+  grub_size_t l;
+
+  *proto = *host = *path = NULL;
+  ps = p = url;
+
+  while ((p = grub_strchr (p, ':')))
+    {
+      if (grub_strlen (p) < sizeof ("://") - 1)
+	break;
+      if (grub_memcmp (p, "://", sizeof ("://") - 1) == 0)
+	{
+	  l = p - ps;
+	  *proto = grub_malloc (l + 1);
+	  if (!*proto)
+	    {
+	      grub_print_error ();
+	      return 0;
+	    }
+
+	  grub_memcpy (*proto, ps, l);
+	  (*proto)[l] = '\0';
+	  p +=  sizeof ("://") - 1;
+	  break;
+	}
+      ++p;
+    }
+
+  if (!*proto)
+    {
+      grub_dprintf ("bootp", "url: %s is not valid, protocol not found\n", url);
+      return 0;
+    }
+
+  ps = p;
+  p = grub_strchr (p, '/');
+
+  if (!p)
+    {
+      grub_dprintf ("bootp", "url: %s is not valid, host/path not found\n", url);
+      grub_free (*proto);
+      *proto = NULL;
+      return 0;
+    }
+
+  l = p - ps;
+
+  if (l > 2 && ps[0] == '[' && ps[l - 1] == ']')
+    {
+      *host = grub_malloc (l - 1);
+      if (!*host)
+	{
+	  grub_print_error ();
+	  grub_free (*proto);
+	  *proto = NULL;
+	  return 0;
+	}
+      grub_memcpy (*host, ps + 1, l - 2);
+      (*host)[l - 2] = 0;
+    }
+  else
+    {
+      *host = grub_malloc (l + 1);
+      if (!*host)
+	{
+	  grub_print_error ();
+	  grub_free (*proto);
+	  *proto = NULL;
+	  return 0;
+	}
+      grub_memcpy (*host, ps, l);
+      (*host)[l] = 0;
+    }
+
+  *path = grub_strdup (p);
+  if (!*path)
+    {
+      grub_print_error ();
+      grub_free (*host);
+      grub_free (*proto);
+      *host = NULL;
+      *proto = NULL;
+      return 0;
+    }
+  return 1;
+}
 
 static void
 parse_dhcp_vendor (const char *name, const void *vend, int limit, int *mask)
@@ -270,6 +362,578 @@ grub_net_configure_by_dhcp_ack (const char *name,
   return inter;
 }
 
+/* The default netbuff size for sending DHCPv6 packets which should be
+   large enough to hold the information */
+#define GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE 512
+
+struct grub_dhcp6_options
+{
+  grub_uint8_t *client_duid;
+  grub_uint16_t client_duid_len;
+  grub_uint8_t *server_duid;
+  grub_uint16_t server_duid_len;
+  grub_uint32_t iaid;
+  grub_uint32_t t1;
+  grub_uint32_t t2;
+  grub_net_network_level_address_t *ia_addr;
+  grub_uint32_t preferred_lifetime;
+  grub_uint32_t valid_lifetime;
+  grub_net_network_level_address_t *dns_server_addrs;
+  grub_uint16_t num_dns_server;
+  char *boot_file_proto;
+  char *boot_file_server_ip;
+  char *boot_file_path;
+};
+
+typedef struct grub_dhcp6_options *grub_dhcp6_options_t;
+
+struct grub_dhcp6_session
+{
+  struct grub_dhcp6_session *next;
+  struct grub_dhcp6_session **prev;
+  grub_uint32_t iaid;
+  grub_uint32_t transaction_id:24;
+  grub_uint64_t start_time;
+  struct grub_net_dhcp6_option_duid_ll duid;
+  struct grub_net_network_level_interface *iface;
+
+  /* The associated dhcpv6 options */
+  grub_dhcp6_options_t adv;
+  grub_dhcp6_options_t reply;
+};
+
+typedef struct grub_dhcp6_session *grub_dhcp6_session_t;
+
+typedef void (*dhcp6_option_hook_fn) (const struct grub_net_dhcp6_option *opt, void *data);
+
+static void
+foreach_dhcp6_option (const struct grub_net_dhcp6_option *opt, grub_size_t size,
+		      dhcp6_option_hook_fn hook, void *hook_data);
+
+static void
+parse_dhcp6_iaaddr (const struct grub_net_dhcp6_option *opt, void *data)
+{
+  grub_dhcp6_options_t dhcp6 = (grub_dhcp6_options_t )data;
+
+  grub_uint16_t code = grub_be_to_cpu16 (opt->code);
+  grub_uint16_t len = grub_be_to_cpu16 (opt->len);
+
+  if (code == GRUB_NET_DHCP6_OPTION_IAADDR)
+    {
+      const struct grub_net_dhcp6_option_iaaddr *iaaddr;
+      iaaddr = (const struct grub_net_dhcp6_option_iaaddr *)opt->data;
+
+      if (len < sizeof (*iaaddr))
+	{
+	  grub_dprintf ("bootp", "DHCPv6: code %u with insufficient length %u\n", code, len);
+	  return;
+	}
+      if (!dhcp6->ia_addr)
+	{
+	  dhcp6->ia_addr = grub_malloc (sizeof(*dhcp6->ia_addr));
+	  dhcp6->ia_addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
+	  dhcp6->ia_addr->ipv6[0] = grub_get_unaligned64 (iaaddr->addr);
+	  dhcp6->ia_addr->ipv6[1] = grub_get_unaligned64 (iaaddr->addr + 8);
+	  dhcp6->preferred_lifetime = grub_be_to_cpu32 (iaaddr->preferred_lifetime);
+	  dhcp6->valid_lifetime = grub_be_to_cpu32 (iaaddr->valid_lifetime);
+	}
+    }
+}
+
+static void
+parse_dhcp6_option (const struct grub_net_dhcp6_option *opt, void *data)
+{
+  grub_dhcp6_options_t dhcp6 = (grub_dhcp6_options_t)data;
+  grub_uint16_t code = grub_be_to_cpu16 (opt->code);
+  grub_uint16_t len = grub_be_to_cpu16 (opt->len);
+
+  switch (code)
+    {
+      case GRUB_NET_DHCP6_OPTION_CLIENTID:
+
+	if (dhcp6->client_duid || !len)
+	  {
+	    grub_dprintf ("bootp", "Skipped DHCPv6 CLIENTID with length %u\n", len);
+	    break;
+	  }
+	dhcp6->client_duid = grub_malloc (len);
+	grub_memcpy (dhcp6->client_duid, opt->data, len);
+	dhcp6->client_duid_len = len;
+	break;
+
+      case GRUB_NET_DHCP6_OPTION_SERVERID:
+
+	if (dhcp6->server_duid || !len)
+	  {
+	    grub_dprintf ("bootp", "Skipped DHCPv6 SERVERID with length %u\n", len);
+	    break;
+	  }
+	dhcp6->server_duid = grub_malloc (len);
+	grub_memcpy (dhcp6->server_duid, opt->data, len);
+	dhcp6->server_duid_len = len;
+	break;
+
+      case GRUB_NET_DHCP6_OPTION_IA_NA:
+	{
+	  const struct grub_net_dhcp6_option_iana *ia_na;
+	  grub_uint16_t data_len;
+
+	  if (dhcp6->iaid || len < sizeof (*ia_na))
+	    {
+	      grub_dprintf ("bootp", "Skipped DHCPv6 IA_NA with length %u\n", len);
+	      break;
+	    }
+	  ia_na = (const struct grub_net_dhcp6_option_iana *)opt->data;
+	  dhcp6->iaid = grub_be_to_cpu32 (ia_na->iaid);
+	  dhcp6->t1 = grub_be_to_cpu32 (ia_na->t1);
+	  dhcp6->t2 = grub_be_to_cpu32 (ia_na->t2);
+
+	  data_len = len - sizeof (*ia_na);
+	  if (data_len)
+	    foreach_dhcp6_option ((const struct grub_net_dhcp6_option *)ia_na->data, data_len, parse_dhcp6_iaaddr, dhcp6);
+	}
+	break;
+
+      case GRUB_NET_DHCP6_OPTION_DNS_SERVERS:
+	{
+	  const grub_uint8_t *po;
+	  grub_uint16_t ln;
+	  grub_net_network_level_address_t *la;
+
+	  if (!len || len & 0xf)
+	    {
+	      grub_dprintf ("bootp", "Skip invalid length DHCPv6 DNS_SERVERS \n");
+	      break;
+	    }
+	  dhcp6->num_dns_server = ln = len >> 4;
+	  dhcp6->dns_server_addrs = la = grub_zalloc (ln * sizeof (*la));
+
+	  for (po = opt->data; ln > 0; po += 0x10, la++, ln--)
+	    {
+	      la->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
+	      la->ipv6[0] = grub_get_unaligned64 (po);
+	      la->ipv6[1] = grub_get_unaligned64 (po + 8);
+	      la->option = DNS_OPTION_PREFER_IPV6;
+	    }
+	}
+	break;
+
+      case GRUB_NET_DHCP6_OPTION_BOOTFILE_URL:
+	dissect_url ((const char *)opt->data,
+		      &dhcp6->boot_file_proto,
+		      &dhcp6->boot_file_server_ip,
+		      &dhcp6->boot_file_path);
+	break;
+
+      default:
+	break;
+    }
+}
+
+static void
+foreach_dhcp6_option (const struct grub_net_dhcp6_option *opt, grub_size_t size, dhcp6_option_hook_fn hook, void *hook_data)
+{
+  while (size)
+    {
+      grub_uint16_t code, len;
+
+      if (size < sizeof (*opt))
+	{
+	  grub_dprintf ("bootp", "DHCPv6: Options stopped with remaining size %" PRIxGRUB_SIZE "\n", size);
+	  break;
+	}
+      size -= sizeof (*opt);
+      len = grub_be_to_cpu16 (opt->len);
+      code = grub_be_to_cpu16 (opt->code);
+      if (size < len)
+	{
+	  grub_dprintf ("bootp", "DHCPv6: Options stopped at out of bound length %u for option %u\n", len, code);
+	  break;
+	}
+      if (!len)
+	{
+	  grub_dprintf ("bootp", "DHCPv6: Options stopped at zero length option %u\n", code);
+	  break;
+	}
+      else
+	{
+	  if (hook)
+	    hook (opt, hook_data);
+	  size -= len;
+	  opt = (const struct grub_net_dhcp6_option *)((grub_uint8_t *)opt + len + sizeof (*opt));
+	}
+    }
+}
+
+static grub_dhcp6_options_t
+grub_dhcp6_options_get (const struct grub_net_dhcp6_packet *v6h,
+			grub_size_t size)
+{
+  grub_dhcp6_options_t options;
+
+  if (size < sizeof (*v6h))
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("DHCPv6 packet size too small"));
+      return NULL;
+    }
+
+  options = grub_zalloc (sizeof(*options));
+  if (!options)
+    return NULL;
+
+  foreach_dhcp6_option ((const struct grub_net_dhcp6_option *)v6h->dhcp_options,
+		       size - sizeof (*v6h), parse_dhcp6_option, options);
+
+  return options;
+}
+
+static void
+grub_dhcp6_options_free (grub_dhcp6_options_t options)
+{
+  if (options->client_duid)
+    grub_free (options->client_duid);
+  if (options->server_duid)
+    grub_free (options->server_duid);
+  if (options->ia_addr)
+    grub_free (options->ia_addr);
+  if (options->dns_server_addrs)
+    grub_free (options->dns_server_addrs);
+  if (options->boot_file_proto)
+    grub_free (options->boot_file_proto);
+  if (options->boot_file_server_ip)
+    grub_free (options->boot_file_server_ip);
+  if (options->boot_file_path)
+    grub_free (options->boot_file_path);
+
+  grub_free (options);
+}
+
+static grub_dhcp6_session_t grub_dhcp6_sessions;
+#define FOR_DHCP6_SESSIONS(var) FOR_LIST_ELEMENTS (var, grub_dhcp6_sessions)
+
+static void
+grub_net_configure_by_dhcp6_info (const char *name,
+	  struct grub_net_card *card,
+	  grub_dhcp6_options_t dhcp6,
+	  int is_def,
+	  int flags,
+	  struct grub_net_network_level_interface **ret_inf)
+{
+  grub_net_network_level_netaddress_t netaddr;
+  struct grub_net_network_level_interface *inf;
+
+  if (dhcp6->ia_addr)
+    {
+      inf = grub_net_add_addr (name, card, dhcp6->ia_addr, &card->default_address, flags);
+
+      netaddr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
+      netaddr.ipv6.base[0] = dhcp6->ia_addr->ipv6[0];
+      netaddr.ipv6.base[1] = 0;
+      netaddr.ipv6.masksize = 64;
+      grub_net_add_route (name, netaddr, inf);
+
+      if (ret_inf)
+	*ret_inf = inf;
+    }
+
+  if (dhcp6->dns_server_addrs)
+    {
+      grub_uint16_t i;
+
+      for (i = 0; i < dhcp6->num_dns_server; ++i)
+	grub_net_add_dns_server (dhcp6->dns_server_addrs + i);
+    }
+
+  if (dhcp6->boot_file_path)
+    grub_env_set_net_property (name, "boot_file", dhcp6->boot_file_path,
+			  grub_strlen (dhcp6->boot_file_path));
+
+  if (is_def && dhcp6->boot_file_server_ip)
+    {
+      grub_net_default_server = grub_strdup (dhcp6->boot_file_server_ip);
+      grub_env_set ("net_default_interface", name);
+      grub_env_export ("net_default_interface");
+    }
+}
+
+static void
+grub_dhcp6_session_add (struct grub_net_network_level_interface *iface,
+			grub_uint32_t iaid)
+{
+  grub_dhcp6_session_t se;
+  struct grub_datetime date;
+  grub_err_t err;
+  grub_int32_t t = 0;
+
+  se = grub_malloc (sizeof (*se));
+
+  err = grub_get_datetime (&date);
+  if (err || !grub_datetime2unixtime (&date, &t))
+    {
+      grub_errno = GRUB_ERR_NONE;
+      t = 0;
+    }
+
+  se->iface = iface;
+  se->iaid = iaid;
+  se->transaction_id = t;
+  se->start_time = grub_get_time_ms ();
+  se->duid.type = grub_cpu_to_be16_compile_time (3) ;
+  se->duid.hw_type = grub_cpu_to_be16_compile_time (1);
+  grub_memcpy (&se->duid.hwaddr, &iface->hwaddress.mac, sizeof (se->duid.hwaddr));
+  se->adv = NULL;
+  se->reply = NULL;
+  grub_list_push (GRUB_AS_LIST_P (&grub_dhcp6_sessions), GRUB_AS_LIST (se));
+}
+
+static void
+grub_dhcp6_session_remove (grub_dhcp6_session_t se)
+{
+  grub_list_remove (GRUB_AS_LIST (se));
+  if (se->adv)
+    grub_dhcp6_options_free (se->adv);
+  if (se->reply)
+    grub_dhcp6_options_free (se->reply);
+  grub_free (se);
+}
+
+static void
+grub_dhcp6_session_remove_all (void)
+{
+  grub_dhcp6_session_t se;
+
+  FOR_DHCP6_SESSIONS (se)
+    {
+      grub_dhcp6_session_remove (se);
+      se = grub_dhcp6_sessions;
+    }
+}
+
+static grub_err_t
+grub_dhcp6_session_configure_network (grub_dhcp6_session_t se)
+{
+  char *name;
+
+  name = grub_xasprintf ("%s:dhcp6", se->iface->card->name);
+  if (!name)
+    return grub_errno;
+
+  grub_net_configure_by_dhcp6_info (name, se->iface->card, se->reply, 1, 0, 0);
+  grub_free (name);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_dhcp6_session_send_request (grub_dhcp6_session_t se)
+{
+  struct grub_net_buff *nb;
+  struct grub_net_dhcp6_option *opt;
+  struct grub_net_dhcp6_packet *v6h;
+  struct grub_net_dhcp6_option_iana *ia_na;
+  struct grub_net_dhcp6_option_iaaddr *iaaddr;
+  struct udphdr *udph;
+  grub_net_network_level_address_t multicast;
+  grub_net_link_level_address_t ll_multicast;
+  grub_uint64_t elapsed;
+  struct grub_net_network_level_interface *inf = se->iface;
+  grub_dhcp6_options_t dhcp6 = se->adv;
+  grub_err_t err = GRUB_ERR_NONE;
+
+  multicast.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
+  multicast.ipv6[0] = grub_cpu_to_be64_compile_time (0xff02ULL << 48);
+  multicast.ipv6[1] = grub_cpu_to_be64_compile_time (0x10002ULL);
+
+  err = grub_net_link_layer_resolve (inf, &multicast, &ll_multicast);
+  if (err)
+    return err;
+
+  nb = grub_netbuff_alloc (GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE);
+
+  if (!nb)
+    return grub_errno;
+
+  err = grub_netbuff_reserve (nb, GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE);
+  if (err)
+    {
+      grub_netbuff_free (nb);
+      return err;
+    }
+
+  err = grub_netbuff_push (nb, dhcp6->client_duid_len + sizeof (*opt));
+  if (err)
+    {
+      grub_netbuff_free (nb);
+      return err;
+    }
+  opt = (struct grub_net_dhcp6_option *)nb->data;
+  opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_CLIENTID);
+  opt->len = grub_cpu_to_be16 (dhcp6->client_duid_len);
+  grub_memcpy (opt->data, dhcp6->client_duid , dhcp6->client_duid_len);
+
+  err = grub_netbuff_push (nb, dhcp6->server_duid_len + sizeof (*opt));
+  if (err)
+    {
+      grub_netbuff_free (nb);
+      return err;
+    }
+  opt = (struct grub_net_dhcp6_option *)nb->data;
+  opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_SERVERID);
+  opt->len = grub_cpu_to_be16 (dhcp6->server_duid_len);
+  grub_memcpy (opt->data, dhcp6->server_duid , dhcp6->server_duid_len);
+
+  err = grub_netbuff_push (nb, sizeof (*ia_na) + sizeof (*opt));
+  if (err)
+    {
+      grub_netbuff_free (nb);
+      return err;
+    }
+
+  if (dhcp6->ia_addr)
+    {
+      err = grub_netbuff_push (nb, sizeof(*iaaddr) + sizeof (*opt));
+      if (err)
+	{
+	  grub_netbuff_free (nb);
+	  return err;
+	}
+    }
+  opt = (struct grub_net_dhcp6_option *)nb->data;
+  opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IA_NA);
+  opt->len = grub_cpu_to_be16 (sizeof (*ia_na));
+  if (dhcp6->ia_addr)
+    opt->len += grub_cpu_to_be16 (sizeof(*iaaddr) + sizeof (*opt));
+
+  ia_na = (struct grub_net_dhcp6_option_iana *)opt->data;
+  ia_na->iaid = grub_cpu_to_be32 (dhcp6->iaid);
+
+  ia_na->t1 = grub_cpu_to_be32 (dhcp6->t1);
+  ia_na->t2 = grub_cpu_to_be32 (dhcp6->t2);
+
+  if (dhcp6->ia_addr)
+    {
+      opt = (struct grub_net_dhcp6_option *)ia_na->data;
+      opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IAADDR);
+      opt->len = grub_cpu_to_be16 (sizeof (*iaaddr));
+      iaaddr = (struct grub_net_dhcp6_option_iaaddr *)opt->data;
+      grub_set_unaligned64 (iaaddr->addr, dhcp6->ia_addr->ipv6[0]);
+      grub_set_unaligned64 (iaaddr->addr + 8, dhcp6->ia_addr->ipv6[1]);
+
+      iaaddr->preferred_lifetime = grub_cpu_to_be32 (dhcp6->preferred_lifetime);
+      iaaddr->valid_lifetime = grub_cpu_to_be32 (dhcp6->valid_lifetime);
+    }
+
+  err = grub_netbuff_push (nb, sizeof (*opt) + 2 * sizeof (grub_uint16_t));
+  if (err)
+    {
+      grub_netbuff_free (nb);
+      return err;
+    }
+
+  opt = (struct grub_net_dhcp6_option*) nb->data;
+  opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_ORO);
+  opt->len = grub_cpu_to_be16_compile_time (2 * sizeof (grub_uint16_t));
+  grub_set_unaligned16 (opt->data, grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_BOOTFILE_URL));
+  grub_set_unaligned16 (opt->data + 2, grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_DNS_SERVERS));
+
+  err = grub_netbuff_push (nb, sizeof (*opt) + sizeof (grub_uint16_t));
+  if (err)
+    {
+      grub_netbuff_free (nb);
+      return err;
+    }
+  opt = (struct grub_net_dhcp6_option*) nb->data;
+  opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_ELAPSED_TIME);
+  opt->len = grub_cpu_to_be16_compile_time (sizeof (grub_uint16_t));
+
+  /* the time is expressed in hundredths of a second */
+  elapsed = grub_divmod64 (grub_get_time_ms () - se->start_time, 10, 0);
+
+  if (elapsed > 0xffff)
+    elapsed = 0xffff;
+
+  grub_set_unaligned16 (opt->data,  grub_cpu_to_be16 ((grub_uint16_t)elapsed));
+
+  err = grub_netbuff_push (nb, sizeof (*v6h));
+  if (err)
+    {
+      grub_netbuff_free (nb);
+      return err;
+    }
+
+  v6h = (struct grub_net_dhcp6_packet *) nb->data;
+  v6h->message_type = GRUB_NET_DHCP6_REQUEST;
+  v6h->transaction_id = se->transaction_id;
+
+  err = grub_netbuff_push (nb, sizeof (*udph));
+  if (err)
+    {
+      grub_netbuff_free (nb);
+      return err;
+    }
+
+  udph = (struct udphdr *) nb->data;
+  udph->src = grub_cpu_to_be16_compile_time (DHCP6_CLIENT_PORT);
+  udph->dst = grub_cpu_to_be16_compile_time (DHCP6_SERVER_PORT);
+  udph->chksum = 0;
+  udph->len = grub_cpu_to_be16 (nb->tail - nb->data);
+
+  udph->chksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_UDP,
+						 &inf->address,
+						 &multicast);
+  err = grub_net_send_ip_packet (inf, &multicast, &ll_multicast, nb,
+				 GRUB_NET_IP_UDP);
+
+  grub_netbuff_free (nb);
+
+  return err;
+}
+
+struct grub_net_network_level_interface *
+grub_net_configure_by_dhcpv6_reply (const char *name,
+	struct grub_net_card *card,
+	grub_net_interface_flags_t flags,
+	const struct grub_net_dhcp6_packet *v6h,
+	grub_size_t size,
+	int is_def,
+	char **device, char **path)
+{
+  struct grub_net_network_level_interface *inf;
+  grub_dhcp6_options_t dhcp6;
+
+  dhcp6 = grub_dhcp6_options_get (v6h, size);
+  if (!dhcp6)
+    {
+      grub_print_error ();
+      return NULL;
+    }
+
+  grub_net_configure_by_dhcp6_info (name, card, dhcp6, is_def, flags, &inf);
+
+  if (device && dhcp6->boot_file_proto && dhcp6->boot_file_server_ip)
+    {
+      *device = grub_xasprintf ("%s,%s", dhcp6->boot_file_proto, dhcp6->boot_file_server_ip);
+      grub_print_error ();
+    }
+  if (path && dhcp6->boot_file_path)
+    {
+      *path = grub_strdup (dhcp6->boot_file_path);
+      grub_print_error ();
+      if (*path)
+	{
+	  char *slash;
+	  slash = grub_strrchr (*path, '/');
+	  if (slash)
+	    *slash = 0;
+	  else
+	    **path = 0;
+	}
+    }
+
+  grub_dhcp6_options_free (dhcp6);
+  return inf;
+}
+
 void
 grub_net_process_dhcp (struct grub_net_buff *nb,
 		       struct grub_net_card *card)
@@ -302,6 +966,77 @@ grub_net_process_dhcp (struct grub_net_buff *nb,
     }
 }
 
+grub_err_t
+grub_net_process_dhcp6 (struct grub_net_buff *nb,
+			struct grub_net_card *card __attribute__ ((unused)))
+{
+  const struct grub_net_dhcp6_packet *v6h;
+  grub_dhcp6_session_t se;
+  grub_size_t size;
+  grub_dhcp6_options_t options;
+
+  v6h = (const struct grub_net_dhcp6_packet *) nb->data;
+  size = nb->tail - nb->data;
+
+  options = grub_dhcp6_options_get (v6h, size);
+  if (!options)
+    return grub_errno;
+
+  if (!options->client_duid || !options->server_duid || !options->ia_addr)
+    {
+      grub_dhcp6_options_free (options);
+      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Bad DHCPv6 Packet");
+    }
+
+  FOR_DHCP6_SESSIONS (se)
+    {
+      if (se->transaction_id == v6h->transaction_id &&
+	  grub_memcmp (options->client_duid, &se->duid, sizeof (se->duid)) == 0 &&
+	  se->iaid == options->iaid)
+	break;
+    }
+
+  if (!se)
+    {
+      grub_dprintf ("bootp", "DHCPv6 session not found\n");
+      grub_dhcp6_options_free (options);
+      return GRUB_ERR_NONE;
+    }
+
+  if (v6h->message_type == GRUB_NET_DHCP6_ADVERTISE)
+    {
+      if (se->adv)
+	{
+	  grub_dprintf ("bootp", "Skipped DHCPv6 Advertised .. \n");
+	  grub_dhcp6_options_free (options);
+	  return GRUB_ERR_NONE;
+	}
+
+      se->adv = options;
+      return grub_dhcp6_session_send_request (se);
+    }
+  else if (v6h->message_type == GRUB_NET_DHCP6_REPLY)
+    {
+      if (!se->adv)
+	{
+	  grub_dprintf ("bootp", "Skipped DHCPv6 Reply .. \n");
+	  grub_dhcp6_options_free (options);
+	  return GRUB_ERR_NONE;
+	}
+
+      se->reply = options;
+      grub_dhcp6_session_configure_network (se);
+      grub_dhcp6_session_remove (se);
+      return GRUB_ERR_NONE;
+    }
+  else
+    {
+      grub_dhcp6_options_free (options);
+    }
+
+  return GRUB_ERR_NONE;
+}
+
 static char
 hexdigit (grub_uint8_t val)
 {
@@ -582,7 +1317,174 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)),
   return err;
 }
 
-static grub_command_t cmd_getdhcp, cmd_bootp;
+static grub_err_t
+grub_cmd_bootp6 (struct grub_command *cmd __attribute__ ((unused)),
+		  int argc, char **args)
+{
+  struct grub_net_card *card;
+  grub_uint32_t iaid = 0;
+  int interval;
+  grub_err_t err;
+  grub_dhcp6_session_t se;
+
+  err = GRUB_ERR_NONE;
+
+  FOR_NET_CARDS (card)
+  {
+    struct grub_net_network_level_interface *iface;
+
+    if (argc > 0 && grub_strcmp (card->name, args[0]) != 0)
+      continue;
+
+    iface = grub_net_ipv6_get_link_local (card, &card->default_address);
+    if (!iface)
+      {
+	grub_dhcp6_session_remove_all ();
+	return grub_errno;
+      }
+
+    grub_dhcp6_session_add (iface, iaid++);
+  }
+
+  for (interval = 200; interval < 10000; interval *= 2)
+    {
+      int done = 1;
+
+      FOR_DHCP6_SESSIONS (se)
+	{
+	  struct grub_net_buff *nb;
+	  struct grub_net_dhcp6_option *opt;
+	  struct grub_net_dhcp6_packet *v6h;
+	  struct grub_net_dhcp6_option_duid_ll *duid;
+	  struct grub_net_dhcp6_option_iana *ia_na;
+	  grub_net_network_level_address_t multicast;
+	  grub_net_link_level_address_t ll_multicast;
+	  struct udphdr *udph;
+
+	  multicast.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
+	  multicast.ipv6[0] = grub_cpu_to_be64_compile_time (0xff02ULL << 48);
+	  multicast.ipv6[1] = grub_cpu_to_be64_compile_time (0x10002ULL);
+
+	  err = grub_net_link_layer_resolve (se->iface,
+		    &multicast, &ll_multicast);
+	  if (err)
+	    {
+	      grub_dhcp6_session_remove_all ();
+	      return err;
+	    }
+
+	  nb = grub_netbuff_alloc (GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE);
+
+	  if (!nb)
+	    {
+	      grub_dhcp6_session_remove_all ();
+	      return grub_errno;
+	    }
+
+	  err = grub_netbuff_reserve (nb, GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE);
+	  if (err)
+	    {
+	      grub_dhcp6_session_remove_all ();
+	      grub_netbuff_free (nb);
+	      return err;
+	    }
+
+	  err = grub_netbuff_push (nb, sizeof (*opt) + sizeof (grub_uint16_t));
+	  if (err)
+	    {
+	      grub_dhcp6_session_remove_all ();
+	      grub_netbuff_free (nb);
+	      return err;
+	    }
+
+	  opt = (struct grub_net_dhcp6_option *)nb->data;
+	  opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_ELAPSED_TIME);
+	  opt->len = grub_cpu_to_be16_compile_time (sizeof (grub_uint16_t));
+	  grub_set_unaligned16 (opt->data, 0);
+
+	  err = grub_netbuff_push (nb, sizeof (*opt) + sizeof (*duid));
+	  if (err)
+	    {
+	      grub_dhcp6_session_remove_all ();
+	      grub_netbuff_free (nb);
+	      return err;
+	    }
+
+	  opt = (struct grub_net_dhcp6_option *)nb->data;
+	  opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_CLIENTID);
+	  opt->len = grub_cpu_to_be16 (sizeof (*duid));
+
+	  duid = (struct grub_net_dhcp6_option_duid_ll *) opt->data;
+	  grub_memcpy (duid, &se->duid, sizeof (*duid));
+
+	  err = grub_netbuff_push (nb, sizeof (*opt) + sizeof (*ia_na));
+	  if (err)
+	    {
+	      grub_dhcp6_session_remove_all ();
+	      grub_netbuff_free (nb);
+	      return err;
+	    }
+
+	  opt = (struct grub_net_dhcp6_option *)nb->data;
+	  opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IA_NA);
+	  opt->len = grub_cpu_to_be16 (sizeof (*ia_na));
+	  ia_na = (struct grub_net_dhcp6_option_iana *)opt->data;
+	  ia_na->iaid = grub_cpu_to_be32 (se->iaid);
+	  ia_na->t1 = 0;
+	  ia_na->t2 = 0;
+
+	  err = grub_netbuff_push (nb, sizeof (*v6h));
+	  if (err)
+	    {
+	      grub_dhcp6_session_remove_all ();
+	      grub_netbuff_free (nb);
+	      return err;
+	    }
+
+	  v6h = (struct grub_net_dhcp6_packet *)nb->data;
+	  v6h->message_type = GRUB_NET_DHCP6_SOLICIT;
+	  v6h->transaction_id = se->transaction_id;
+
+	  grub_netbuff_push (nb, sizeof (*udph));
+
+	  udph = (struct udphdr *) nb->data;
+	  udph->src = grub_cpu_to_be16_compile_time (DHCP6_CLIENT_PORT);
+	  udph->dst = grub_cpu_to_be16_compile_time (DHCP6_SERVER_PORT);
+	  udph->chksum = 0;
+	  udph->len = grub_cpu_to_be16 (nb->tail - nb->data);
+
+	  udph->chksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_UDP,
+			    &se->iface->address, &multicast);
+
+	  err = grub_net_send_ip_packet (se->iface, &multicast,
+		    &ll_multicast, nb, GRUB_NET_IP_UDP);
+	  done = 0;
+	  grub_netbuff_free (nb);
+
+	  if (err)
+	    {
+	      grub_dhcp6_session_remove_all ();
+	      return err;
+	    }
+	}
+      if (!done)
+	grub_net_poll_cards (interval, 0);
+    }
+
+  FOR_DHCP6_SESSIONS (se)
+    {
+      grub_error_push ();
+      err = grub_error (GRUB_ERR_FILE_NOT_FOUND,
+			N_("couldn't autoconfigure %s"),
+			se->iface->card->name);
+    }
+
+  grub_dhcp6_session_remove_all ();
+
+  return err;
+}
+
+static grub_command_t cmd_getdhcp, cmd_bootp, cmd_bootp6;
 
 void
 grub_bootp_init (void)
@@ -593,6 +1495,9 @@ grub_bootp_init (void)
   cmd_getdhcp = grub_register_command ("net_get_dhcp_option", grub_cmd_dhcpopt,
 				       N_("VAR INTERFACE NUMBER DESCRIPTION"),
 				       N_("retrieve DHCP option and save it into VAR. If VAR is - then print the value."));
+  cmd_bootp6 = grub_register_command ("net_bootp6", grub_cmd_bootp6,
+				     N_("[CARD]"),
+				     N_("perform a DHCPv6 autoconfiguration"));
 }
 
 void
@@ -600,4 +1505,5 @@ grub_bootp_fini (void)
 {
   grub_unregister_command (cmd_getdhcp);
   grub_unregister_command (cmd_bootp);
+  grub_unregister_command (cmd_bootp6);
 }
diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c
index aba4f89..59970ab 100644
--- a/grub-core/net/ip.c
+++ b/grub-core/net/ip.c
@@ -238,6 +238,45 @@ handle_dgram (struct grub_net_buff *nb,
   {
     struct udphdr *udph;
     udph = (struct udphdr *) nb->data;
+
+    if (proto == GRUB_NET_IP_UDP && udph->dst == grub_cpu_to_be16_compile_time (DHCP6_CLIENT_PORT))
+      {
+	if (udph->chksum)
+	  {
+	    grub_uint16_t chk, expected;
+	    chk = udph->chksum;
+	    udph->chksum = 0;
+	    expected = grub_net_ip_transport_checksum (nb,
+						       GRUB_NET_IP_UDP,
+						       source,
+						       dest);
+	    if (expected != chk)
+	      {
+		grub_dprintf ("net", "Invalid UDP checksum. "
+			      "Expected %x, got %x\n",
+			      grub_be_to_cpu16 (expected),
+			      grub_be_to_cpu16 (chk));
+		grub_netbuff_free (nb);
+		return GRUB_ERR_NONE;
+	      }
+	    udph->chksum = chk;
+	  }
+
+	err = grub_netbuff_pull (nb, sizeof (*udph));
+	if (err)
+	  {
+	    grub_netbuff_free (nb);
+	    return err;
+	  }
+
+	err = grub_net_process_dhcp6 (nb, card);
+	if (err)
+	  grub_print_error ();
+
+	grub_netbuff_free (nb);
+	return GRUB_ERR_NONE;
+      }
+
     if (proto == GRUB_NET_IP_UDP && grub_be_to_cpu16 (udph->dst) == 68)
       {
 	const struct grub_net_bootp_packet *bootp;
diff --git a/include/grub/net.h b/include/grub/net.h
index d13ee61..6133da5 100644
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -443,6 +443,66 @@ struct grub_net_bootp_packet
   grub_uint8_t vendor[0];
 } GRUB_PACKED;
 
+struct grub_net_dhcp6_packet
+{
+  grub_uint32_t message_type:8;
+  grub_uint32_t transaction_id:24;
+  grub_uint8_t dhcp_options[0];
+} GRUB_PACKED;
+
+struct grub_net_dhcp6_option {
+  grub_uint16_t code;
+  grub_uint16_t len;
+  grub_uint8_t data[0];
+} GRUB_PACKED;
+
+struct grub_net_dhcp6_option_iana {
+  grub_uint32_t iaid;
+  grub_uint32_t t1;
+  grub_uint32_t t2;
+  grub_uint8_t data[0];
+} GRUB_PACKED;
+
+struct grub_net_dhcp6_option_iaaddr {
+  grub_uint8_t addr[16];
+  grub_uint32_t preferred_lifetime;
+  grub_uint32_t valid_lifetime;
+  grub_uint8_t data[0];
+} GRUB_PACKED;
+
+struct grub_net_dhcp6_option_duid_ll
+{
+  grub_uint16_t type;
+  grub_uint16_t hw_type;
+  grub_uint8_t hwaddr[6];
+} GRUB_PACKED;
+
+enum
+  {
+    GRUB_NET_DHCP6_SOLICIT = 1,
+    GRUB_NET_DHCP6_ADVERTISE = 2,
+    GRUB_NET_DHCP6_REQUEST = 3,
+    GRUB_NET_DHCP6_REPLY = 7
+  };
+
+enum
+  {
+    DHCP6_CLIENT_PORT = 546,
+    DHCP6_SERVER_PORT = 547
+  };
+
+enum
+  {
+    GRUB_NET_DHCP6_OPTION_CLIENTID = 1,
+    GRUB_NET_DHCP6_OPTION_SERVERID = 2,
+    GRUB_NET_DHCP6_OPTION_IA_NA = 3,
+    GRUB_NET_DHCP6_OPTION_IAADDR = 5,
+    GRUB_NET_DHCP6_OPTION_ORO = 6,
+    GRUB_NET_DHCP6_OPTION_ELAPSED_TIME = 8,
+    GRUB_NET_DHCP6_OPTION_DNS_SERVERS = 23,
+    GRUB_NET_DHCP6_OPTION_BOOTFILE_URL = 59
+  };
+
 #define	GRUB_NET_BOOTP_RFC1048_MAGIC_0	0x63
 #define	GRUB_NET_BOOTP_RFC1048_MAGIC_1	0x82
 #define	GRUB_NET_BOOTP_RFC1048_MAGIC_2	0x53
@@ -469,6 +529,14 @@ grub_net_configure_by_dhcp_ack (const char *name,
 				grub_size_t size,
 				int is_def, char **device, char **path);
 
+struct grub_net_network_level_interface *
+grub_net_configure_by_dhcpv6_reply (const char *name,
+				    struct grub_net_card *card,
+				    grub_net_interface_flags_t flags,
+				    const struct grub_net_dhcp6_packet *v6,
+				    grub_size_t size,
+				    int is_def, char **device, char **path);
+
 grub_err_t
 grub_net_add_ipv4_local (struct grub_net_network_level_interface *inf,
 			 int mask);
@@ -477,6 +545,10 @@ void
 grub_net_process_dhcp (struct grub_net_buff *nb,
 		       struct grub_net_card *card);
 
+grub_err_t
+grub_net_process_dhcp6 (struct grub_net_buff *nb,
+			struct grub_net_card *card);
+
 int
 grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a,
 		     const grub_net_link_level_address_t *b);
-- 
2.7.4



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

* [PATCH 5/9] efinet: UEFI IPv6 PXE support
  2016-12-23  8:54 [PATCH v2 0/9] Add UEFI HTTP Boot support for IPv4 and IPv6 Keng-Yu Lin
                   ` (3 preceding siblings ...)
  2016-12-23  8:54 ` [PATCH 4/9] bootp: New net_bootp6 command Keng-Yu Lin
@ 2016-12-23  8:54 ` Keng-Yu Lin
  2016-12-23  8:54 ` [PATCH 6/9] grub.texi: Add net_bootp6 doument Keng-Yu Lin
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Keng-Yu Lin @ 2016-12-23  8:54 UTC (permalink / raw)
  To: grub-devel; +Cc: mchang, ken.lin, ljk, michael.ruan, clayc, kengyu

From: Michael Chang <mchang@suse.com>

When grub2 image is booted from UEFI IPv6 PXE, the DHCPv6 Reply packet is
cached in firmware buffer which can be obtained by PXE Base Code protocol. The
network interface can be setup through the parameters in that obtained packet.

Signed-off-by: Michael Chang <mchang@suse.com>
Signed-off-by: Ken Lin <ken.lin@hpe.com>
---
 grub-core/net/drivers/efi/efinet.c | 24 +++++++++++++----
 include/grub/efi/api.h             | 55 +++++++++++++++++++++++++++++++++++++-
 2 files changed, 73 insertions(+), 6 deletions(-)

diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
index 5388f95..fc90415 100644
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -378,11 +378,25 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
     if (! pxe)
       continue;
     pxe_mode = pxe->mode;
-    grub_net_configure_by_dhcp_ack (card->name, card, 0,
-				    (struct grub_net_bootp_packet *)
-				    &pxe_mode->dhcp_ack,
-				    sizeof (pxe_mode->dhcp_ack),
-				    1, device, path);
+
+    if (pxe_mode->using_ipv6)
+      {
+	grub_net_configure_by_dhcpv6_reply (card->name, card, 0,
+					    (struct grub_net_dhcp6_packet *)
+					    &pxe_mode->dhcp_ack,
+					    sizeof (pxe_mode->dhcp_ack),
+					    1, device, path);
+	if (grub_errno)
+	  grub_print_error ();
+      }
+    else
+      {
+	grub_net_configure_by_dhcp_ack (card->name, card, 0,
+					(struct grub_net_bootp_packet *)
+					&pxe_mode->dhcp_ack,
+					sizeof (pxe_mode->dhcp_ack),
+					1, device, path);
+      }
     return;
   }
 }
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index c7c9f0e..92f9b5a 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -1452,14 +1452,67 @@ typedef struct grub_efi_simple_text_output_interface grub_efi_simple_text_output
 
 typedef grub_uint8_t grub_efi_pxe_packet_t[1472];
 
+typedef struct {
+  grub_uint8_t addr[4];
+} grub_efi_pxe_ipv4_address_t;
+
+typedef struct {
+  grub_uint8_t addr[16];
+} grub_efi_pxe_ipv6_address_t;
+
+typedef struct {
+  grub_uint8_t addr[32];
+} grub_efi_pxe_mac_address_t;
+
+typedef union {
+    grub_uint32_t addr[4];
+    grub_efi_pxe_ipv4_address_t v4;
+    grub_efi_pxe_ipv6_address_t v6;
+} grub_efi_pxe_ip_address_t;
+
+#define GRUB_EFI_PXE_BASE_CODE_MAX_IPCNT 8
+typedef struct {
+    grub_uint8_t filters;
+    grub_uint8_t ip_cnt;
+    grub_uint16_t reserved;
+    grub_efi_pxe_ip_address_t ip_list[GRUB_EFI_PXE_BASE_CODE_MAX_IPCNT];
+} grub_efi_pxe_ip_filter_t;
+
+typedef struct {
+    grub_efi_pxe_ip_address_t ip_addr;
+    grub_efi_pxe_mac_address_t mac_addr;
+} grub_efi_pxe_arp_entry_t;
+
+typedef struct {
+    grub_efi_pxe_ip_address_t ip_addr;
+    grub_efi_pxe_ip_address_t subnet_mask;
+    grub_efi_pxe_ip_address_t gw_addr;
+} grub_efi_pxe_route_entry_t;
+
+
+#define GRUB_EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES 8
+#define GRUB_EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES 8
+
 typedef struct grub_efi_pxe_mode
 {
-  grub_uint8_t unused[52];
+  grub_uint8_t started;
+  grub_uint8_t ipv6_available;
+  grub_uint8_t ipv6_supported;
+  grub_uint8_t using_ipv6;
+  grub_uint8_t unused[16];
+  grub_efi_pxe_ip_address_t station_ip;
+  grub_efi_pxe_ip_address_t subnet_mask;
   grub_efi_pxe_packet_t dhcp_discover;
   grub_efi_pxe_packet_t dhcp_ack;
   grub_efi_pxe_packet_t proxy_offer;
   grub_efi_pxe_packet_t pxe_discover;
   grub_efi_pxe_packet_t pxe_reply;
+  grub_efi_pxe_packet_t pxe_bis_reply;
+  grub_efi_pxe_ip_filter_t ip_filter;
+  grub_uint32_t arp_cache_entries;
+  grub_efi_pxe_arp_entry_t arp_cache[GRUB_EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES];
+  grub_uint32_t route_table_entries;
+  grub_efi_pxe_route_entry_t route_table[GRUB_EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES];
 } grub_efi_pxe_mode_t;
 
 typedef struct grub_efi_pxe
-- 
2.7.4



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

* [PATCH 6/9] grub.texi: Add net_bootp6 doument
  2016-12-23  8:54 [PATCH v2 0/9] Add UEFI HTTP Boot support for IPv4 and IPv6 Keng-Yu Lin
                   ` (4 preceding siblings ...)
  2016-12-23  8:54 ` [PATCH 5/9] efinet: UEFI IPv6 PXE support Keng-Yu Lin
@ 2016-12-23  8:54 ` Keng-Yu Lin
  2016-12-23  8:54 ` [PATCH 7/9] bootp: Add processing DHCPACK packet from HTTP Boot Keng-Yu Lin
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Keng-Yu Lin @ 2016-12-23  8:54 UTC (permalink / raw)
  To: grub-devel; +Cc: mchang, ken.lin, ljk, michael.ruan, clayc, kengyu

From: Michael Chang <mchang@suse.com>

Update grub documentation for net_bootp6 command.

Signed-off-by: Michael Chang <mchang@suse.com>
Signed-off-by: Ken Lin <ken.lin@hpe.com>
---
 docs/grub.texi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/docs/grub.texi b/docs/grub.texi
index b9ddb9b..7f7e4f4 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -5184,6 +5184,7 @@ See @uref{http://wiki.xen.org/wiki/XSM} for more detail.
 * net_add_dns::                 Add a DNS server
 * net_add_route::               Add routing entry
 * net_bootp::                   Perform a bootp autoconfiguration
+* net_bootp6::                  Perform a DHCPv6 autoconfiguration
 * net_del_addr::                Remove IP address from interface
 * net_del_dns::                 Remove a DNS server
 * net_del_route::               Remove a route entry
@@ -5265,6 +5266,22 @@ Sets environment variable @samp{net_}@var{<card>}@samp{_dhcp_extensionspath}
 
 @end deffn
 
+@node net_bootp6
+@subsection net_bootp6
+
+@deffn Command net_bootp6 [@var{card}]
+Perform configuration of @var{card} using DHCPv6 protocol. If no card name is
+specified, try to configure all existing cards. If configuration was
+successful, interface with name @var{card}@samp{:dhcp6} and configured address
+is added to @var{card}.
+
+@table @samp
+@item 1 (Domain Name Server)
+Adds all servers from option value to the list of servers used during name
+resolution.
+@end table
+
+@end deffn
 
 @node net_del_addr
 @subsection net_del_addr
-- 
2.7.4



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

* [PATCH 7/9] bootp: Add processing DHCPACK packet from HTTP Boot
  2016-12-23  8:54 [PATCH v2 0/9] Add UEFI HTTP Boot support for IPv4 and IPv6 Keng-Yu Lin
                   ` (5 preceding siblings ...)
  2016-12-23  8:54 ` [PATCH 6/9] grub.texi: Add net_bootp6 doument Keng-Yu Lin
@ 2016-12-23  8:54 ` Keng-Yu Lin
  2016-12-23  8:54 ` [PATCH 8/9] efinet: Setting network from UEFI device path Keng-Yu Lin
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Keng-Yu Lin @ 2016-12-23  8:54 UTC (permalink / raw)
  To: grub-devel; +Cc: mchang, ken.lin, ljk, michael.ruan, clayc, kengyu

From: Michael Chang <mchang@suse.com>

The vendor class identifier with the string "HTTPClient" is used to denote the
packet as responding to HTTP boot request. In DHCP4 config, the filename for
HTTP boot is the URL of the boot file while for PXE boot it is the path to the
boot file. As a consequence, the next-server becomes obseleted because the HTTP
URL already contains the server address for the boot file. For DHCP6 config,
there's no difference definition in existing config as dhcp6.bootfile-url can
be used to specify URL for both HTTP and PXE boot file.

This patch adds processing for "HTTPClient" vendor class identifier in DHCPACK
packet by treating it as HTTP format, not as the PXE format.

Signed-off-by: Michael Chang <mchang@suse.com>
Signed-off-by: Ken Lin <ken.lin@hpe.com>
---
 grub-core/net/bootp.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++--
 include/grub/net.h    |  1 +
 2 files changed, 66 insertions(+), 2 deletions(-)

diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
index 172528e..de9239c 100644
--- a/grub-core/net/bootp.c
+++ b/grub-core/net/bootp.c
@@ -207,6 +207,11 @@ parse_dhcp_vendor (const char *name, const void *vend, int limit, int *mask)
                                      taglength);
           break;
 
+        case GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER:
+          grub_env_set_net_property (name, "vendor_class_identifier", (const char *) ptr,
+                                     taglength);
+	  break;
+
 	case GRUB_NET_BOOTP_EXTENSIONS_PATH:
           grub_env_set_net_property (name, "extensionspath", (const char *) ptr,
                                      taglength);
@@ -282,6 +287,66 @@ grub_net_configure_by_dhcp_ack (const char *name,
     }
 #endif
 
+  if (size > OFFSET_OF (vendor, bp))
+    {
+      char *cidvar;
+      const char *cid;
+
+      parse_dhcp_vendor (name, &bp->vendor, size - OFFSET_OF (vendor, bp), &mask);
+      cidvar = grub_xasprintf ("net_%s_%s", name, "vendor_class_identifier");
+      cid = grub_env_get (cidvar);
+      grub_free (cidvar);
+
+      if (cid && grub_strcmp (cid, "HTTPClient") == 0)
+	{
+	  char *proto, *ip, *pa;
+
+	  if (!dissect_url (bp->boot_file, &proto, &ip, &pa))
+	    return inter;
+
+	  grub_env_set_net_property (name, "boot_file", pa, grub_strlen (pa));
+	  if (is_def)
+	    {
+	      grub_net_default_server = grub_strdup (ip);
+	      grub_env_set ("net_default_interface", name);
+	      grub_env_export ("net_default_interface");
+	    }
+	  if (device && !*device)
+	    {
+	      *device = grub_xasprintf ("%s,%s", proto, ip);
+	      grub_print_error ();
+	    }
+	  if (path)
+	    {
+	      *path = grub_strdup (pa);
+	      grub_print_error ();
+	      if (*path)
+		{
+		  char *slash;
+		  slash = grub_strrchr (*path, '/');
+		  if (slash)
+		    *slash = 0;
+		  else
+		    **path = 0;
+		}
+	    }
+	  grub_net_add_ipv4_local (inter, mask);
+	  inter->dhcp_ack = grub_malloc (size);
+	  if (inter->dhcp_ack)
+	    {
+	      grub_memcpy (inter->dhcp_ack, bp, size);
+	      inter->dhcp_acklen = size;
+	    }
+	  else
+	    grub_errno = GRUB_ERR_NONE;
+
+	  grub_free (proto);
+	  grub_free (ip);
+	  grub_free (pa);
+	  return inter;
+	}
+    }
+
   if (size > OFFSET_OF (boot_file, bp))
     grub_env_set_net_property (name, "boot_file", bp->boot_file,
                                sizeof (bp->boot_file));
@@ -346,8 +411,6 @@ grub_net_configure_by_dhcp_ack (const char *name,
 	    **path = 0;
 	}
     }
-  if (size > OFFSET_OF (vendor, bp))
-    parse_dhcp_vendor (name, &bp->vendor, size - OFFSET_OF (vendor, bp), &mask);
   grub_net_add_ipv4_local (inter, mask);
   
   inter->dhcp_ack = grub_malloc (size);
diff --git a/include/grub/net.h b/include/grub/net.h
index 6133da5..67c801e 100644
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -518,6 +518,7 @@ enum
     GRUB_NET_BOOTP_DOMAIN = 0x0f,
     GRUB_NET_BOOTP_ROOT_PATH = 0x11,
     GRUB_NET_BOOTP_EXTENSIONS_PATH = 0x12,
+    GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER = 0x3C,
     GRUB_NET_BOOTP_END = 0xff
   };
 
-- 
2.7.4



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

* [PATCH 8/9] efinet: Setting network from UEFI device path
  2016-12-23  8:54 [PATCH v2 0/9] Add UEFI HTTP Boot support for IPv4 and IPv6 Keng-Yu Lin
                   ` (6 preceding siblings ...)
  2016-12-23  8:54 ` [PATCH 7/9] bootp: Add processing DHCPACK packet from HTTP Boot Keng-Yu Lin
@ 2016-12-23  8:54 ` Keng-Yu Lin
  2016-12-23  8:54 ` [PATCH 9/9] efinet: Setting DNS server from UEFI protocol Keng-Yu Lin
  2017-01-16  9:07 ` [PATCH v2 0/9] Add UEFI HTTP Boot support for IPv4 and IPv6 Lin, Keng-Yu (HPS OE-Linux TDC)
  9 siblings, 0 replies; 17+ messages in thread
From: Keng-Yu Lin @ 2016-12-23  8:54 UTC (permalink / raw)
  To: grub-devel; +Cc: mchang, ken.lin, ljk, michael.ruan, clayc, kengyu

From: Michael Chang <mchang@suse.com>

The PXE Base Code protocol used to obtain cached PXE DHCPACK packet is no
longer provided for HTTP Boot. Instead, we have to get the HTTP boot
information from the device path nodes defined in following UEFI Specification
sections.

 9.3.5.12 IPv4 Device Path
 9.3.5.13 IPv6 Device Path
 9.3.5.23 Uniform Resource Identifiers (URI) Device Path

This patch basically does:

include/grub/efi/api.h:
Add new structure of Uniform Resource Identifiers (URI) Device Path

grub-core/net/drivers/efi/efinet.c:
Check if PXE Base Code is available, if not it will try to obtain the netboot
information from the device path where the image booted from. The DHCPACK
packet is recoverd from the information in device patch and feed into the same
DHCP packet processing functions to ensure the network interface is setting up
the same way it used to be.

Signed-off-by: Michael Chang <mchang@suse.com>
Signed-off-by: Ken Lin <ken.lin@hpe.com>
---
 grub-core/net/drivers/efi/efinet.c | 268 +++++++++++++++++++++++++++++++++++--
 include/grub/efi/api.h             |  11 ++
 2 files changed, 270 insertions(+), 9 deletions(-)

diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
index fc90415..2d3b00f 100644
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -23,6 +23,7 @@
 #include <grub/efi/api.h>
 #include <grub/efi/efi.h>
 #include <grub/i18n.h>
+#include <grub/net/netbuff.h>
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
@@ -324,6 +325,221 @@ grub_efinet_findcards (void)
   grub_free (handles);
 }
 
+static struct grub_net_buff *
+grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *use_ipv6)
+{
+  grub_efi_uint16_t uri_len;
+  grub_efi_device_path_t *ldp, *ddp;
+  grub_efi_uri_device_path_t *uri_dp;
+  struct grub_net_buff *nb;
+  grub_err_t err;
+
+  ddp = grub_efi_duplicate_device_path (dp);
+  ldp = grub_efi_find_last_device_path (ddp);
+
+  if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
+      || GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)
+    {
+      grub_free (ddp);
+      return NULL;
+    }
+
+  uri_len = GRUB_EFI_DEVICE_PATH_LENGTH (ldp) > 4 ? GRUB_EFI_DEVICE_PATH_LENGTH (ldp) - 4  : 0;
+
+  if (!uri_len)
+    {
+      grub_free (ddp);
+      return NULL;
+    }
+
+  uri_dp = (grub_efi_uri_device_path_t *) ldp;
+
+  ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+  ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+  ldp->length = sizeof (*ldp);
+
+  ldp = grub_efi_find_last_device_path (ddp);
+
+  if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
+      || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
+          && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE))
+    {
+      grub_free (ddp);
+      return NULL;
+    }
+
+  nb = grub_netbuff_alloc (512);
+  if (!nb)
+    return NULL;
+
+  if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE)
+    {
+      grub_efi_ipv4_device_path_t *ipv4 = (grub_efi_ipv4_device_path_t *) ldp;
+      struct grub_net_bootp_packet *bp;
+      grub_uint8_t *ptr;
+
+      bp = (struct grub_net_bootp_packet *) nb->tail;
+      err = grub_netbuff_put (nb, sizeof (*bp) + 4);
+      if (err)
+	{
+	  grub_free (ddp);
+	  grub_netbuff_free (nb);
+	  return NULL;
+	}
+
+      if (sizeof(bp->boot_file) < uri_len)
+	{
+	  grub_free (ddp);
+	  grub_netbuff_free (nb);
+	  return NULL;
+	}
+      grub_memcpy (bp->boot_file, uri_dp->uri, uri_len);
+      grub_memcpy (&bp->your_ip, ipv4->local_ip_address, sizeof (bp->your_ip));
+      grub_memcpy (&bp->server_ip, ipv4->remote_ip_address, sizeof (bp->server_ip));
+
+      bp->vendor[0] = GRUB_NET_BOOTP_RFC1048_MAGIC_0;
+      bp->vendor[1] = GRUB_NET_BOOTP_RFC1048_MAGIC_1;
+      bp->vendor[2] = GRUB_NET_BOOTP_RFC1048_MAGIC_2;
+      bp->vendor[3] = GRUB_NET_BOOTP_RFC1048_MAGIC_3;
+
+      ptr = nb->tail;
+      err = grub_netbuff_put (nb, sizeof (ipv4->subnet_mask) + 2);
+      if (err)
+	{
+	  grub_free (ddp);
+	  grub_netbuff_free (nb);
+	  return NULL;
+	}
+      *ptr++ = GRUB_NET_BOOTP_NETMASK;
+      *ptr++ = sizeof (ipv4->subnet_mask);
+      grub_memcpy (ptr, ipv4->subnet_mask, sizeof (ipv4->subnet_mask));
+
+      ptr = nb->tail;
+      err = grub_netbuff_put (nb, sizeof (ipv4->gateway_ip_address) + 2);
+      if (err)
+	{
+	  grub_free (ddp);
+	  grub_netbuff_free (nb);
+	  return NULL;
+	}
+      *ptr++ = GRUB_NET_BOOTP_ROUTER;
+      *ptr++ = sizeof (ipv4->gateway_ip_address);
+      grub_memcpy (ptr, ipv4->gateway_ip_address, sizeof (ipv4->gateway_ip_address));
+
+      ptr = nb->tail;
+      err = grub_netbuff_put (nb, sizeof ("HTTPClient") + 1);
+      if (err)
+	{
+	  grub_free (ddp);
+	  grub_netbuff_free (nb);
+	  return NULL;
+	}
+      *ptr++ = GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER;
+      *ptr++ = sizeof ("HTTPClient") - 1;
+      grub_memcpy (ptr, "HTTPClient", sizeof ("HTTPClient") - 1);
+
+      ptr = nb->tail;
+      err = grub_netbuff_put (nb, 1);
+      if (err)
+	{
+	  grub_free (ddp);
+	  grub_netbuff_free (nb);
+	  return NULL;
+	}
+      *ptr = GRUB_NET_BOOTP_END;
+      *use_ipv6 = 0;
+
+      ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+      ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+      ldp->length = sizeof (*ldp);
+      ldp = grub_efi_find_last_device_path (ddp);
+
+      if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) ==  GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE)
+	{
+	  grub_efi_mac_address_device_path_t *mac = (grub_efi_mac_address_device_path_t *) ldp;
+	  bp->hw_type = mac->if_type;
+	  bp->hw_len = sizeof (bp->mac_addr);
+	  grub_memcpy (bp->mac_addr, mac->mac_address, bp->hw_len);
+	}
+    }
+  else
+    {
+      grub_efi_ipv6_device_path_t *ipv6 = (grub_efi_ipv6_device_path_t *) ldp;
+
+      struct grub_net_dhcp6_packet *d6p;
+      struct grub_net_dhcp6_option *opt;
+      struct grub_net_dhcp6_option_iana *iana;
+      struct grub_net_dhcp6_option_iaaddr *iaaddr;
+
+      d6p = (struct grub_net_dhcp6_packet *)nb->tail;
+      err = grub_netbuff_put (nb, sizeof(*d6p));
+      if (err)
+	{
+	  grub_free (ddp);
+	  grub_netbuff_free (nb);
+	  return NULL;
+	}
+      d6p->message_type = GRUB_NET_DHCP6_REPLY;
+
+      opt = (struct grub_net_dhcp6_option *)nb->tail;
+      err = grub_netbuff_put (nb, sizeof(*opt));
+      if (err)
+	{
+	  grub_free (ddp);
+	  grub_netbuff_free (nb);
+	  return NULL;
+	}
+      opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IA_NA);
+      opt->len = grub_cpu_to_be16_compile_time (sizeof(*iana) + sizeof(*opt) + sizeof(*iaaddr));
+
+      err = grub_netbuff_put (nb, sizeof(*iana));
+      if (err)
+	{
+	  grub_free (ddp);
+	  grub_netbuff_free (nb);
+	  return NULL;
+	}
+
+      opt = (struct grub_net_dhcp6_option *)nb->tail;
+      err = grub_netbuff_put (nb, sizeof(*opt));
+      if (err)
+	{
+	  grub_free (ddp);
+	  grub_netbuff_free (nb);
+	  return NULL;
+	}
+      opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IAADDR);
+      opt->len = grub_cpu_to_be16_compile_time (sizeof (*iaaddr));
+
+      iaaddr = (struct grub_net_dhcp6_option_iaaddr *)nb->tail;
+      err = grub_netbuff_put (nb, sizeof(*iaaddr));
+      if (err)
+	{
+	  grub_free (ddp);
+	  grub_netbuff_free (nb);
+	  return NULL;
+	}
+      grub_memcpy (iaaddr->addr, ipv6->local_ip_address, sizeof(ipv6->local_ip_address));
+
+      opt = (struct grub_net_dhcp6_option *)nb->tail;
+      err = grub_netbuff_put (nb, sizeof(*opt) + uri_len);
+      if (err)
+	{
+	  grub_free (ddp);
+	  grub_netbuff_free (nb);
+	  return NULL;
+	}
+      opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_BOOTFILE_URL);
+      opt->len = grub_cpu_to_be16 (uri_len);
+      grub_memcpy (opt->data, uri_dp->uri, uri_len);
+
+      *use_ipv6 = 1;
+    }
+
+  grub_free (ddp);
+  return nb;
+}
+
 static void
 grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
 			  char **path)
@@ -340,6 +556,11 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
     grub_efi_device_path_t *cdp;
     struct grub_efi_pxe *pxe;
     struct grub_efi_pxe_mode *pxe_mode;
+    grub_uint8_t *packet_buf;
+    grub_size_t packet_bufsz ;
+    int ipv6;
+    struct grub_net_buff *nb = NULL;
+
     if (card->driver != &efidriver)
       continue;
     cdp = grub_efi_get_device_path (card->efi_handle);
@@ -359,11 +580,21 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
 	ldp = grub_efi_find_last_device_path (dp);
 	if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
 	    || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
-		&& GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE))
+		&& GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE
+		&& GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_URI_DEVICE_PATH_SUBTYPE))
 	  continue;
 	dup_dp = grub_efi_duplicate_device_path (dp);
 	if (!dup_dp)
 	  continue;
+
+	if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)
+	  {
+	    dup_ldp = grub_efi_find_last_device_path (dup_dp);
+	    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);
+	  }
+
 	dup_ldp = grub_efi_find_last_device_path (dup_dp);
 	dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
 	dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
@@ -375,16 +606,31 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
       }
     pxe = grub_efi_open_protocol (hnd, &pxe_io_guid,
 				  GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
-    if (! pxe)
-      continue;
-    pxe_mode = pxe->mode;
+    if (!pxe)
+      {
+	nb = grub_efinet_create_dhcp_ack_from_device_path (dp, &ipv6);
+	if (!nb)
+	  {
+	    grub_print_error ();
+	    continue;
+	  }
+	packet_buf = nb->head;
+	packet_bufsz = nb->tail - nb->head;
+      }
+    else
+      {
+	pxe_mode = pxe->mode;
+	packet_buf = (grub_uint8_t *) &pxe_mode->dhcp_ack;
+	packet_bufsz = sizeof (pxe_mode->dhcp_ack);
+	ipv6 = pxe_mode->using_ipv6;
+      }
 
-    if (pxe_mode->using_ipv6)
+    if (ipv6)
       {
 	grub_net_configure_by_dhcpv6_reply (card->name, card, 0,
 					    (struct grub_net_dhcp6_packet *)
-					    &pxe_mode->dhcp_ack,
-					    sizeof (pxe_mode->dhcp_ack),
+					    packet_buf,
+					    packet_bufsz,
 					    1, device, path);
 	if (grub_errno)
 	  grub_print_error ();
@@ -393,10 +639,14 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
       {
 	grub_net_configure_by_dhcp_ack (card->name, card, 0,
 					(struct grub_net_bootp_packet *)
-					&pxe_mode->dhcp_ack,
-					sizeof (pxe_mode->dhcp_ack),
+					packet_buf,
+					packet_bufsz,
 					1, device, path);
       }
+
+    if (nb)
+      grub_netbuff_free (nb);
+
     return;
   }
 }
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index 92f9b5a..d5a1256 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -825,6 +825,8 @@ struct grub_efi_ipv4_device_path
   grub_efi_uint16_t remote_port;
   grub_efi_uint16_t protocol;
   grub_efi_uint8_t static_ip_address;
+  grub_efi_ipv4_address_t gateway_ip_address;
+  grub_efi_ipv4_address_t subnet_mask;
 } GRUB_PACKED;
 typedef struct grub_efi_ipv4_device_path grub_efi_ipv4_device_path_t;
 
@@ -879,6 +881,15 @@ struct grub_efi_sata_device_path
 } GRUB_PACKED;
 typedef struct grub_efi_sata_device_path grub_efi_sata_device_path_t;
 
+#define GRUB_EFI_URI_DEVICE_PATH_SUBTYPE		24
+
+struct grub_efi_uri_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_uint8_t uri[0];
+} GRUB_PACKED;
+typedef struct grub_efi_uri_device_path grub_efi_uri_device_path_t;
+
 #define GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE	10
 
 /* Media Device Path.  */
-- 
2.7.4



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

* [PATCH 9/9] efinet: Setting DNS server from UEFI protocol
  2016-12-23  8:54 [PATCH v2 0/9] Add UEFI HTTP Boot support for IPv4 and IPv6 Keng-Yu Lin
                   ` (7 preceding siblings ...)
  2016-12-23  8:54 ` [PATCH 8/9] efinet: Setting network from UEFI device path Keng-Yu Lin
@ 2016-12-23  8:54 ` Keng-Yu Lin
  2017-01-16  9:07 ` [PATCH v2 0/9] Add UEFI HTTP Boot support for IPv4 and IPv6 Lin, Keng-Yu (HPS OE-Linux TDC)
  9 siblings, 0 replies; 17+ messages in thread
From: Keng-Yu Lin @ 2016-12-23  8:54 UTC (permalink / raw)
  To: grub-devel; +Cc: mchang, ken.lin, ljk, michael.ruan, clayc, kengyu

From: Michael Chang <mchang@suse.com>

In the URI device path node, any name rahter than address can be used for
looking up the resources so that DNS service become needed to get answer of the
name's address. Unfortunately the DNS is not defined in any of the device path
nodes so that we use the EFI_IP4_CONFIG2_PROTOCOL and EFI_IP6_CONFIG_PROTOCOL
to obtain it.

These two protcols are defined the sections of UEFI specification.

 27.5 EFI IPv4 Configuration II Protocol
 27.7 EFI IPv6 Configuration Protocol

include/grub/efi/api.h:
Add new structure and protocol UUID of EFI_IP4_CONFIG2_PROTOCOL and
EFI_IP6_CONFIG_PROTOCOL.

grub-core/net/drivers/efi/efinet.c:
Use the EFI_IP4_CONFIG2_PROTOCOL and EFI_IP6_CONFIG_PROTOCOL to obtain the list
of DNS server address for IPv4 and IPv6 respectively. The address of DNS
servers is structured into DHCPACK packet and feed into the same DHCP packet
processing functions to ensure the network interface is setting up the same way
it used to be.

Signed-off-by: Michael Chang <mchang@suse.com>
Signed-off-by: Ken Lin <ken.lin@hpe.com>
---
 grub-core/net/drivers/efi/efinet.c | 163 +++++++++++++++++++++++++++++++++++++
 include/grub/efi/api.h             |  76 +++++++++++++++++
 2 files changed, 239 insertions(+)

diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
index 2d3b00f..82a28fb 100644
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -30,6 +30,8 @@ GRUB_MOD_LICENSE ("GPLv3+");
 /* GUID.  */
 static grub_efi_guid_t net_io_guid = GRUB_EFI_SIMPLE_NETWORK_GUID;
 static grub_efi_guid_t pxe_io_guid = GRUB_EFI_PXE_GUID;
+static grub_efi_guid_t ip4_config_guid = GRUB_EFI_IP4_CONFIG2_PROTOCOL_GUID;
+static grub_efi_guid_t ip6_config_guid = GRUB_EFI_IP6_CONFIG_PROTOCOL_GUID;
 
 static grub_err_t
 send_card_buffer (struct grub_net_card *dev,
@@ -325,6 +327,125 @@ grub_efinet_findcards (void)
   grub_free (handles);
 }
 
+static grub_efi_handle_t
+grub_efi_locate_device_path (grub_efi_guid_t *protocol, grub_efi_device_path_t *device_path,
+			    grub_efi_device_path_t **r_device_path)
+{
+  grub_efi_handle_t handle;
+  grub_efi_status_t status;
+
+  status = efi_call_3 (grub_efi_system_table->boot_services->locate_device_path,
+		      protocol, &device_path, &handle);
+
+  if (status != GRUB_EFI_SUCCESS)
+    return 0;
+
+  if (r_device_path)
+    *r_device_path = device_path;
+
+  return handle;
+}
+
+static grub_efi_ipv4_address_t *
+grub_dns_server_ip4_address (grub_efi_device_path_t *dp, grub_efi_uintn_t *num_dns)
+{
+  grub_efi_handle_t hnd;
+  grub_efi_status_t status;
+  grub_efi_ip4_config2_protocol_t *conf;
+  grub_efi_ipv4_address_t *addrs;
+  grub_efi_uintn_t data_size = 1 * sizeof (grub_efi_ipv4_address_t);
+
+  hnd = grub_efi_locate_device_path (&ip4_config_guid, dp, NULL);
+
+  if (!hnd)
+    return 0;
+
+  conf = grub_efi_open_protocol (hnd, &ip4_config_guid,
+				GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+  if (!conf)
+    return 0;
+
+  addrs  = grub_malloc (data_size);
+  if (!addrs)
+    return 0;
+
+  status = efi_call_4 (conf->get_data, conf,
+		      GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER,
+		      &data_size, addrs);
+
+  if (status == GRUB_EFI_BUFFER_TOO_SMALL)
+    {
+      grub_free (addrs);
+      addrs  = grub_malloc (data_size);
+      if (!addrs)
+	return 0;
+
+      status = efi_call_4 (conf->get_data,  conf,
+			  GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER,
+			  &data_size, addrs);
+    }
+
+  if (status != GRUB_EFI_SUCCESS)
+    {
+      grub_free (addrs);
+      return 0;
+    }
+
+  *num_dns = data_size / sizeof (grub_efi_ipv4_address_t);
+  return addrs;
+}
+
+static grub_efi_ipv6_address_t *
+grub_dns_server_ip6_address (grub_efi_device_path_t *dp, grub_efi_uintn_t *num_dns)
+{
+  grub_efi_handle_t hnd;
+  grub_efi_status_t status;
+  grub_efi_ip6_config_protocol_t *conf;
+  grub_efi_ipv6_address_t *addrs;
+  grub_efi_uintn_t data_size = 1 * sizeof (grub_efi_ipv6_address_t);
+
+  hnd = grub_efi_locate_device_path (&ip6_config_guid, dp, NULL);
+
+  if (!hnd)
+    return 0;
+
+  conf = grub_efi_open_protocol (hnd, &ip6_config_guid,
+				GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+  if (!conf)
+    return 0;
+
+  addrs  = grub_malloc (data_size);
+  if (!addrs)
+    return 0;
+
+  status = efi_call_4 (conf->get_data, conf,
+		      GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER,
+		      &data_size, addrs);
+
+  if (status == GRUB_EFI_BUFFER_TOO_SMALL)
+    {
+      grub_free (addrs);
+      addrs  = grub_malloc (data_size);
+      if (!addrs)
+	return 0;
+
+      status = efi_call_4 (conf->get_data,  conf,
+			  GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER,
+			  &data_size, addrs);
+    }
+
+  if (status != GRUB_EFI_SUCCESS)
+    {
+      grub_free (addrs);
+      return 0;
+    }
+
+  *num_dns = data_size / sizeof (grub_efi_ipv6_address_t);
+  return addrs;
+}
+
 static struct grub_net_buff *
 grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *use_ipv6)
 {
@@ -377,6 +498,8 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u
       grub_efi_ipv4_device_path_t *ipv4 = (grub_efi_ipv4_device_path_t *) ldp;
       struct grub_net_bootp_packet *bp;
       grub_uint8_t *ptr;
+      grub_efi_ipv4_address_t *dns;
+      grub_efi_uintn_t num_dns;
 
       bp = (struct grub_net_bootp_packet *) nb->tail;
       err = grub_netbuff_put (nb, sizeof (*bp) + 4);
@@ -438,6 +561,25 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u
       *ptr++ = sizeof ("HTTPClient") - 1;
       grub_memcpy (ptr, "HTTPClient", sizeof ("HTTPClient") - 1);
 
+      dns = grub_dns_server_ip4_address (dp, &num_dns);
+      if (dns)
+	{
+	  grub_efi_uintn_t size_dns = sizeof (*dns) * num_dns;
+
+	  ptr = nb->tail;
+	  err = grub_netbuff_put (nb, size_dns + 2);
+	  if (err)
+	    {
+	      grub_free (ddp);
+	      grub_netbuff_free (nb);
+	      return NULL;
+	    }
+	  *ptr++ = GRUB_NET_BOOTP_DNS;
+	  *ptr++ = size_dns;
+	  grub_memcpy (ptr, dns, size_dns);
+	  grub_free (dns);
+	}
+
       ptr = nb->tail;
       err = grub_netbuff_put (nb, 1);
       if (err)
@@ -470,6 +612,8 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u
       struct grub_net_dhcp6_option *opt;
       struct grub_net_dhcp6_option_iana *iana;
       struct grub_net_dhcp6_option_iaaddr *iaaddr;
+      grub_efi_ipv6_address_t *dns;
+      grub_efi_uintn_t num_dns;
 
       d6p = (struct grub_net_dhcp6_packet *)nb->tail;
       err = grub_netbuff_put (nb, sizeof(*d6p));
@@ -533,6 +677,25 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u
       opt->len = grub_cpu_to_be16 (uri_len);
       grub_memcpy (opt->data, uri_dp->uri, uri_len);
 
+      dns = grub_dns_server_ip6_address (dp, &num_dns);
+      if (dns)
+	{
+	  grub_efi_uintn_t size_dns = sizeof (*dns) * num_dns;
+
+	  opt = (struct grub_net_dhcp6_option *)nb->tail;
+	  err = grub_netbuff_put (nb, sizeof(*opt) + size_dns);
+	  if (err)
+	  {
+	    grub_free (ddp);
+	    grub_netbuff_free (nb);
+	    return NULL;
+	  }
+	  opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_DNS_SERVERS);
+	  opt->len = grub_cpu_to_be16 (size_dns);
+	  grub_memcpy (opt->data, dns, size_dns);
+	  grub_free (dns);
+	}
+
       *use_ipv6 = 1;
     }
 
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index d5a1256..99ba068 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -334,6 +334,16 @@
       { 0x8B, 0x8C, 0xE2, 0x1B, 0x01, 0xAE, 0xF2, 0xB7 } \
   }
 
+#define GRUB_EFI_IP4_CONFIG2_PROTOCOL_GUID \
+  { 0x5b446ed1, 0xe30b, 0x4faa, \
+      { 0x87, 0x1a, 0x36, 0x54, 0xec, 0xa3, 0x60, 0x80 } \
+  }
+
+#define GRUB_EFI_IP6_CONFIG_PROTOCOL_GUID \
+  { 0x937fe521, 0x95ae, 0x4d1a, \
+      { 0x89, 0x29, 0x48, 0xbc, 0xd9, 0x0a, 0xd3, 0x1a } \
+  }
+
 struct grub_efi_sal_system_table
 {
   grub_uint32_t signature;
@@ -1749,6 +1759,72 @@ struct grub_efi_block_io
 };
 typedef struct grub_efi_block_io grub_efi_block_io_t;
 
+enum grub_efi_ip4_config2_data_type {
+  GRUB_EFI_IP4_CONFIG2_DATA_TYPE_INTERFACEINFO,
+  GRUB_EFI_IP4_CONFIG2_DATA_TYPE_POLICY,
+  GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS,
+  GRUB_EFI_IP4_CONFIG2_DATA_TYPE_GATEWAY,
+  GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER,
+  GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MAXIMUM
+};
+typedef enum grub_efi_ip4_config2_data_type grub_efi_ip4_config2_data_type_t;
+
+struct grub_efi_ip4_config2_protocol
+{
+  grub_efi_status_t (*set_data) (struct grub_efi_ip4_config2_protocol *this,
+				 grub_efi_ip4_config2_data_type_t data_type,
+				 grub_efi_uintn_t data_size,
+				 void *data);
+
+  grub_efi_status_t (*get_data) (struct grub_efi_ip4_config2_protocol *this,
+				 grub_efi_ip4_config2_data_type_t data_type,
+				 grub_efi_uintn_t *data_size,
+				 void *data);
+
+  grub_efi_status_t (*register_data_notify) (struct grub_efi_ip4_config2_protocol *this,
+					     grub_efi_ip4_config2_data_type_t data_type,
+					     grub_efi_event_t event);
+
+  grub_efi_status_t (*unregister_datanotify) (struct grub_efi_ip4_config2_protocol *this,
+					     grub_efi_ip4_config2_data_type_t data_type,
+					     grub_efi_event_t event);
+};
+typedef struct grub_efi_ip4_config2_protocol grub_efi_ip4_config2_protocol_t;
+
+enum grub_efi_ip6_config_data_type {
+  GRUB_EFI_IP6_CONFIG_DATA_TYPE_INTERFACEINFO,
+  GRUB_EFI_IP6_CONFIG_DATA_TYPE_ALT_INTERFACEID,
+  GRUB_EFI_IP6_CONFIG_DATA_TYPE_POLICY,
+  GRUB_EFI_IP6_CONFIG_DATA_TYPE_DUP_ADDR_DETECT_TRANSMITS,
+  GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS,
+  GRUB_EFI_IP6_CONFIG_DATA_TYPE_GATEWAY,
+  GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER,
+  GRUB_EFI_IP6_CONFIG_DATA_TYPE_MAXIMUM
+};
+typedef enum grub_efi_ip6_config_data_type grub_efi_ip6_config_data_type_t;
+
+struct grub_efi_ip6_config_protocol
+{
+  grub_efi_status_t (*set_data) (struct grub_efi_ip6_config_protocol *this,
+				 grub_efi_ip6_config_data_type_t data_type,
+				 grub_efi_uintn_t data_size,
+				 void *data);
+
+  grub_efi_status_t (*get_data) (struct grub_efi_ip6_config_protocol *this,
+				 grub_efi_ip6_config_data_type_t data_type,
+				 grub_efi_uintn_t *data_size,
+				 void *data);
+
+  grub_efi_status_t (*register_data_notify) (struct grub_efi_ip6_config_protocol *this,
+					     grub_efi_ip6_config_data_type_t data_type,
+					     grub_efi_event_t event);
+
+  grub_efi_status_t (*unregister_datanotify) (struct grub_efi_ip6_config_protocol *this,
+					     grub_efi_ip6_config_data_type_t data_type,
+					     grub_efi_event_t event);
+};
+typedef struct grub_efi_ip6_config_protocol grub_efi_ip6_config_protocol_t;
+
 #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \
   || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__)
 
-- 
2.7.4



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

* RE: [PATCH v2 0/9] Add UEFI HTTP Boot support for IPv4 and IPv6
  2016-12-23  8:54 [PATCH v2 0/9] Add UEFI HTTP Boot support for IPv4 and IPv6 Keng-Yu Lin
                   ` (8 preceding siblings ...)
  2016-12-23  8:54 ` [PATCH 9/9] efinet: Setting DNS server from UEFI protocol Keng-Yu Lin
@ 2017-01-16  9:07 ` Lin, Keng-Yu (HPS OE-Linux TDC)
  2017-01-16 10:12   ` Daniel Kiper
  9 siblings, 1 reply; 17+ messages in thread
From: Lin, Keng-Yu (HPS OE-Linux TDC) @ 2017-01-16  9:07 UTC (permalink / raw)
  To: grub-devel, arvidjaar, phcoder, daniel.kiper
  Cc: mchang, Lin, Ken (HPS OE-Linux TDC),
	Knippers, Linda, Ruan, Michael (HPS OE-Linux/VMware TDC),
	Chang, Clay (HPS OE-Linux TDC)

Hi there,
  There has been a while since the patchset is sent. There is no comment so far.
  Wonder if it is in a good shape and will be merged soon?

    Thanks for the reviewing effort. :-)
-kengyu

-----Original Message-----
From: Lin, Keng-Yu (HPS OE-Linux TDC) 
Sent: Friday, December 23, 2016 4:54 PM
To: grub-devel@gnu.org
Cc: mchang@suse.com; Lin, Ken (HPS OE-Linux TDC) <ken.lin@hpe.com>; Knippers, Linda <linda.knippers@hpe.com>; Ruan, Michael (HPS OE-Linux/VMware TDC) <michael.ruan@hpe.com>; Chang, Clay (HPS OE-Linux TDC) <clayc@hpe.com>; Lin, Keng-Yu (HPS OE-Linux TDC) <keng-yu.lin@hpe.com>
Subject: [PATCH v2 0/9] Add UEFI HTTP Boot support for IPv4 and IPv6

The patchset is a follow-up to the previous one sent in Auguest.
After talking with Michael Chang, he is happy that we pick up this.

This patchset was tested on a machine with EDK2-derived ROM.
Both ipv4 and ipv6 are tested. The default http port (80) and a specified port (we chose 79) are also tested. All passed.

See below for more explanation for each patch.

Aaron Miller (1):
  net: read bracketed ipv6 addrs and port numbers

Keng-Yu Lin (1):
  Add default port in grub_net_app_protocol

This one is the main one in reply the last review.
Besides adding the default port grub_net_app_protocol, this patch also shortened the port string and add a comment to the code for adding the brackets for un-brackted ipv6 address. The brackets are required based on the testing result on the real machine.

For port 0, this is not realistic for the real use, because there is no way for the http server to know in advance which port the client will get. However, I removed all port 0 checking. From the source-level, port 0 should work.

Michael Chang (6):
  bootp: New net_bootp6 command
  efinet: UEFI IPv6 PXE support
  grub.texi: Add net_bootp6 doument
  bootp: Add processing DHCPACK packet from HTTP Boot
  efinet: Setting network from UEFI device path
  efinet: Setting DNS server from UEFI protocol

Vladimir Serbinenko (1):
  strtoull: Fix behaviour on chars between '9' and 'a'.

Dropped Aaron Miller's patch and use this one since it is now in the grub/next branch. One thing to notice is that the test case is missing. It causes compiling to fail. We teporarily removed the test case from grub-core/Makefile.core.def in our testing.


 docs/grub.texi                        |  17 +
 grub-core/Makefile.core.def           |   5 +
 grub-core/kern/misc.c                 |  13 +-
 grub-core/net/bootp.c                 | 975 +++++++++++++++++++++++++++++++++-
 grub-core/net/drivers/efi/efinet.c    | 445 +++++++++++++++-
 grub-core/net/http.c                  |  21 +-
 grub-core/net/ip.c                    |  39 ++
 grub-core/net/net.c                   |  91 +++-
 grub-core/net/tftp.c                  |   9 +-
 grub-core/tests/lib/functional_test.c |  13 +-
 include/grub/efi/api.h                | 142 ++++-
 include/grub/net.h                    |  75 +++
 12 files changed, 1809 insertions(+), 36 deletions(-)

--
1.8.3.1



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

* Re: [PATCH v2 0/9] Add UEFI HTTP Boot support for IPv4 and IPv6
  2017-01-16  9:07 ` [PATCH v2 0/9] Add UEFI HTTP Boot support for IPv4 and IPv6 Lin, Keng-Yu (HPS OE-Linux TDC)
@ 2017-01-16 10:12   ` Daniel Kiper
  2017-07-06  6:52     ` Lin, Keng-Yu
  0 siblings, 1 reply; 17+ messages in thread
From: Daniel Kiper @ 2017-01-16 10:12 UTC (permalink / raw)
  To: Lin, Keng-Yu (HPS OE-Linux TDC)
  Cc: grub-devel, arvidjaar, phcoder, mchang, Lin,
	Ken (HPS OE-Linux TDC),
	Knippers, Linda, Ruan, Michael (HPS OE-Linux/VMware TDC),
	Chang, Clay (HPS OE-Linux TDC)

Hi Keng-Yu,

Sorry for late reply but I clearing my backlog after long vacation.

On Mon, Jan 16, 2017 at 09:07:53AM +0000, Lin, Keng-Yu (HPS OE-Linux TDC) wrote:
> Hi there,
>   There has been a while since the patchset is sent. There is no comment so far.
>   Wonder if it is in a good shape and will be merged soon?
>
>     Thanks for the reviewing effort. :-)

Thank you for doing the work. Unfortunately it is too late to put it
into 2.02 release (I hope it will happen at the end of February or at
beginning of March). I am adding this patch set to review after release.
Please be patient.

Daniel


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

* RE: [PATCH v2 0/9] Add UEFI HTTP Boot support for IPv4 and IPv6
  2017-01-16 10:12   ` Daniel Kiper
@ 2017-07-06  6:52     ` Lin, Keng-Yu
  2017-07-10 10:10       ` Michael Chang
  2017-07-10 20:41       ` Daniel Kiper
  0 siblings, 2 replies; 17+ messages in thread
From: Lin, Keng-Yu @ 2017-07-06  6:52 UTC (permalink / raw)
  To: The development of GNU GRUB
  Cc: Knippers, Linda, arvidjaar, phcoder, Chang,
	Clay (HPS OE-Linux TDC), Ruan, Michael (HPS OE-Linux/VMware TDC),
	mchang

> Hi Keng-Yu,
>
> Sorry for late reply but I clearing my backlog after long vacation.
>
>
> Thank you for doing the work. Unfortunately it is too late to put it into 2.02 release (I hope it will happen at the end of February or at beginning of March). I am adding this patch set to review > after release.
> Please be patient.
>
> Daniel

Hi Daniel:
  Wonder if there is any chance to get this patchset moving on.
  This patchset was well tested on both Qemu/EDK2 and some real HPE ProLiant Gen10 machines.
  (check the cover letter for more details.)

  Let me know if there is anything further I can help. :-)

  Thanks,
-kengyu


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

* Re: [PATCH v2 0/9] Add UEFI HTTP Boot support for IPv4 and IPv6
  2017-07-06  6:52     ` Lin, Keng-Yu
@ 2017-07-10 10:10       ` Michael Chang
  2017-07-11  7:39         ` Lin, Keng-Yu
  2017-07-10 20:41       ` Daniel Kiper
  1 sibling, 1 reply; 17+ messages in thread
From: Michael Chang @ 2017-07-10 10:10 UTC (permalink / raw)
  To: The development of GNU GRUB
  Cc: Knippers, Linda, arvidjaar, phcoder, Chang,
	Clay (HPS OE-Linux TDC), Ruan, Michael (HPS OE-Linux/VMware TDC)

On Thu, Jul 06, 2017 at 06:52:02AM +0000, Lin, Keng-Yu wrote:
> > Hi Keng-Yu,
> >
> > Sorry for late reply but I clearing my backlog after long vacation.
> >
> >
> > Thank you for doing the work. Unfortunately it is too late to put it into 2.02 release (I hope it will happen at the end of February or at beginning of March). I am adding this patch set to review > after release.
> > Please be patient.
> >
> > Daniel
> 
> Hi Daniel:
>   Wonder if there is any chance to get this patchset moving on.
>   This patchset was well tested on both Qemu/EDK2 and some real HPE ProLiant Gen10 machines.
>   (check the cover letter for more details.)

How many test case did you perform on this patch. More specifically, did you
verify how does it work with existing network commands

 https://www.gnu.org/software/grub/manual/grub.html#Networking-commands

And also environment variables related to network

  https://www.gnu.org/software/grub/manual/grub.html#Network

I think the patch is good at running grub booted directly by UEFI http load
file protocol, assuming the UEFI Handle has configured network protocol down
the road before handing over to grub. But that may not satisfied the user as
they get used to have more than that already.
 
Practically grub can work out more (sophisticated) scenario by exercising the
network commands to configure the network interface one way or the other, and
obviously the patch did not route the same commands to UEFI network stack,
which is regarded as functional regression as it did not apply on UEFI
protocol.

Thanks,
Michael

> 	
>   Let me know if there is anything further I can help. :-)
> 
>   Thanks,
> -kengyu
> 
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel


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

* Re: [PATCH v2 0/9] Add UEFI HTTP Boot support for IPv4 and IPv6
  2017-07-06  6:52     ` Lin, Keng-Yu
  2017-07-10 10:10       ` Michael Chang
@ 2017-07-10 20:41       ` Daniel Kiper
  1 sibling, 0 replies; 17+ messages in thread
From: Daniel Kiper @ 2017-07-10 20:41 UTC (permalink / raw)
  To: keng-yu.lin, grub-devel
  Cc: Knippers, Linda, arvidjaar, phcoder, Chang,
	Clay (HPS OE-Linux TDC), Ruan, Michael (HPS OE-Linux/VMware TDC),
	mchang

Hi Keng-Yu,

On Thu, Jul 06, 2017 at 06:52:02AM +0000, Lin, Keng-Yu wrote:
> > Hi Keng-Yu,
> >
> > Sorry for late reply but I clearing my backlog after long vacation.
> >
> >
> > Thank you for doing the work. Unfortunately it is too late to put it into 2.02 release (I hope it will happen at the end of February or at beginning of March). I am adding this patch set to review > after release.
> > Please be patient.
> >
> > Daniel
>
> Hi Daniel:
>   Wonder if there is any chance to get this patchset moving on.
>   This patchset was well tested on both Qemu/EDK2 and some real HPE ProLiant Gen10 machines.
>   (check the cover letter for more details.)
>
>   Let me know if there is anything further I can help. :-)

I am traveling this week. I will take a look at the patches probably next
week. In the mean time please address the questions raised by Michael.

Daniel


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

* RE: [PATCH v2 0/9] Add UEFI HTTP Boot support for IPv4 and IPv6
  2017-07-10 10:10       ` Michael Chang
@ 2017-07-11  7:39         ` Lin, Keng-Yu
  2017-07-11  9:48           ` Michael Chang
  0 siblings, 1 reply; 17+ messages in thread
From: Lin, Keng-Yu @ 2017-07-11  7:39 UTC (permalink / raw)
  To: The development of GNU GRUB
  Cc: Knippers, Linda, arvidjaar, Chang, Clay (HPS OE-Linux TDC),
	Ruan, Michael (HPS OE-Linux/VMware TDC),
	phcoder

> How many test case did you perform on this patch. More specifically, did you
> verify how does it work with existing network commands
> 
>  https://www.gnu.org/software/grub/manual/grub.html#Networking-
> commands
> 
> And also environment variables related to network
> 
>   https://www.gnu.org/software/grub/manual/grub.html#Network
> 
> I think the patch is good at running grub booted directly by UEFI http load file
> protocol, assuming the UEFI Handle has configured network protocol down
> the road before handing over to grub. But that may not satisfied the user as
> they get used to have more than that already.
> 
> Practically grub can work out more (sophisticated) scenario by exercising the
> network commands to configure the network interface one way or the other,
> and obviously the patch did not route the same commands to UEFI network
> stack, which is regarded as functional regression as it did not apply on UEFI
> protocol.

Hi Michael:
  Thanks for the comments. 
  Are you saying that for this patchset, the following environment variables should be supported in the UEFI HTTP Boot mode too?

  * 'net_<interface>_ip'
  *'net_<interface>_mac'
  * 'net_<interface>_hostname'
  * 'net_<interface>_domain'
  * 'net_<interface>_rootpath'
  * 'net_<interface>_extensionspath'
  * 'net_<interface>_boot_file'
  * 'net_<interface>_dhcp_server_name'
  * 'net_<interface>_next_server'
  * 'net_default_interface'
  * 'net_default_ip'
  * 'net_default_mac'
  * 'net_default_server'

  And the following commands:

* net_add_addr:    Add a network address  
* net_add_dns:    Add a DNS server  
* net_add_route:    Add routing entry  
* net_bootp:    Perform a bootp autoconfiguration  
* net_del_addr:    Remove IP address from interface  
* net_del_dns:    Remove a DNS server  
* net_del_route:    Remove a route entry  
* net_get_dhcp_option:    Retrieve DHCP options  
* net_ipv6_autoconf:    Perform IPv6 autoconfiguration  
* net_ls_addr:    List interfaces  
* net_ls_cards:    List network cards  
* net_ls_dns:    List DNS servers  
* net_ls_routes:    List routing entries  
* net_nslookup:    Perform a DNS lookup  


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

* Re: [PATCH v2 0/9] Add UEFI HTTP Boot support for IPv4 and IPv6
  2017-07-11  7:39         ` Lin, Keng-Yu
@ 2017-07-11  9:48           ` Michael Chang
  0 siblings, 0 replies; 17+ messages in thread
From: Michael Chang @ 2017-07-11  9:48 UTC (permalink / raw)
  To: The development of GNU GRUB
  Cc: Knippers, Linda, arvidjaar, Chang, Clay (HPS OE-Linux TDC),
	Ruan, Michael (HPS OE-Linux/VMware TDC),
	phcoder

On Tue, Jul 11, 2017 at 07:39:16AM +0000, Lin, Keng-Yu wrote:
> > How many test case did you perform on this patch. More specifically, did you
> > verify how does it work with existing network commands
> > 
> >  https://www.gnu.org/software/grub/manual/grub.html#Networking-
> > commands
> > 
> > And also environment variables related to network
> > 
> >   https://www.gnu.org/software/grub/manual/grub.html#Network
> > 
> > I think the patch is good at running grub booted directly by UEFI http load file
> > protocol, assuming the UEFI Handle has configured network protocol down
> > the road before handing over to grub. But that may not satisfied the user as
> > they get used to have more than that already.
> > 
> > Practically grub can work out more (sophisticated) scenario by exercising the
> > network commands to configure the network interface one way or the other,
> > and obviously the patch did not route the same commands to UEFI network
> > stack, which is regarded as functional regression as it did not apply on UEFI
> > protocol.
> 
> Hi Michael:
>   Thanks for the comments. 
>   Are you saying that for this patchset, the following environment variables should be supported in the UEFI HTTP Boot mode too?

Yes. And it should not be limited to http but also PXE mode of the UEFI.
Afterall, the UEFI should be acting like alternative module of networking at
user's disposal and should not notice any difference.

Thanks,
Michael

> 
>   * 'net_<interface>_ip'
>   *'net_<interface>_mac'
>   * 'net_<interface>_hostname'
>   * 'net_<interface>_domain'
>   * 'net_<interface>_rootpath'
>   * 'net_<interface>_extensionspath'
>   * 'net_<interface>_boot_file'
>   * 'net_<interface>_dhcp_server_name'
>   * 'net_<interface>_next_server'
>   * 'net_default_interface'
>   * 'net_default_ip'
>   * 'net_default_mac'
>   * 'net_default_server'
> 
>   And the following commands:
> 
> * net_add_addr:    Add a network address  
> * net_add_dns:    Add a DNS server  
> * net_add_route:    Add routing entry  
> * net_bootp:    Perform a bootp autoconfiguration  
> * net_del_addr:    Remove IP address from interface  
> * net_del_dns:    Remove a DNS server  
> * net_del_route:    Remove a route entry  
> * net_get_dhcp_option:    Retrieve DHCP options  
> * net_ipv6_autoconf:    Perform IPv6 autoconfiguration  
> * net_ls_addr:    List interfaces  
> * net_ls_cards:    List network cards  
> * net_ls_dns:    List DNS servers  
> * net_ls_routes:    List routing entries  
> * net_nslookup:    Perform a DNS lookup  
> 
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel


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

end of thread, other threads:[~2017-07-11 10:11 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-23  8:54 [PATCH v2 0/9] Add UEFI HTTP Boot support for IPv4 and IPv6 Keng-Yu Lin
2016-12-23  8:54 ` [PATCH 1/9] strtoull: Fix behaviour on chars between '9' and 'a' Keng-Yu Lin
2016-12-23  8:54 ` [PATCH 2/9] net: read bracketed ipv6 addrs and port numbers Keng-Yu Lin
2016-12-23  8:54 ` [PATCH v2 3/9] Add default port in grub_net_app_protocol Keng-Yu Lin
2016-12-23  8:54 ` [PATCH 4/9] bootp: New net_bootp6 command Keng-Yu Lin
2016-12-23  8:54 ` [PATCH 5/9] efinet: UEFI IPv6 PXE support Keng-Yu Lin
2016-12-23  8:54 ` [PATCH 6/9] grub.texi: Add net_bootp6 doument Keng-Yu Lin
2016-12-23  8:54 ` [PATCH 7/9] bootp: Add processing DHCPACK packet from HTTP Boot Keng-Yu Lin
2016-12-23  8:54 ` [PATCH 8/9] efinet: Setting network from UEFI device path Keng-Yu Lin
2016-12-23  8:54 ` [PATCH 9/9] efinet: Setting DNS server from UEFI protocol Keng-Yu Lin
2017-01-16  9:07 ` [PATCH v2 0/9] Add UEFI HTTP Boot support for IPv4 and IPv6 Lin, Keng-Yu (HPS OE-Linux TDC)
2017-01-16 10:12   ` Daniel Kiper
2017-07-06  6:52     ` Lin, Keng-Yu
2017-07-10 10:10       ` Michael Chang
2017-07-11  7:39         ` Lin, Keng-Yu
2017-07-11  9:48           ` Michael Chang
2017-07-10 20:41       ` Daniel Kiper

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.