Re: Proposal v2: fs/iso9660: Prevent skipping CE or ST at start of continuation area

2023-01-09 Thread Thomas Schmitt
Hi,

Lidong Chen wrote:
> Thanks for the clarification. I created a new patch for the fix and added
> you as the “Signed-off-by”.
> My question is how to test it.

I just sent libisofs into an endless recursion loop. Grrr.
For this i created a small ISO with a file which surely needs a CE, changed
its fields so that it points to itself, and attempted to load it by xorriso.
(At least it ends by SIGSEGV on an exhausted stack and does not cycle
endlessly.)

--
ISO creation:

   # A dummy file as payload
   echo x >x

   # 250 fattr characters to surely exceed the size of a directory entry
   
long_string=0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789

   # Create ISO with the payload file and attached fattr named user.dummy
   test -e ce_loop.iso && rm ce_loop.iso
   xorriso -outdev ce_loop.iso \
   -xattr on \
   -map x /x \
   -setfattr user.dummy "$long_string" /x -- \
   -padding 0

Next i determined by a hex dumper the location of the only Rock Ridge
entry NM and then the location of the next following CE entry (the first
CE belongs to the root directory):
  Byte 102734 decimal = 50 * 2048 + 334 = LBA 0x32 + Offset 0x014e
The size of the continuation area is 270 = 0x010e
The length of CE is 28 = 0x1c

So i patched the own address and size of the CE entry into its fields:

  # The block address (little endian and big endian)
  echo $'\x32' | dd bs=1 seek=102738 count=1 conv=notrunc of=ce_loop.iso
  echo $'\x32' | dd bs=1 seek=102745 count=1 conv=notrunc of=ce_loop.iso

  # The byte offset in that block
  echo $'\x4e'$'\x01' | dd bs=1 seek=102746 count=2 conv=notrunc of=ce_loop.iso
  echo $'\x01'$'\x4e' | dd bs=1 seek=102752 count=2 conv=notrunc of=ce_loop.iso

  # The new size of the CE area is the length of the CE entry
  echo $'\x1c' | dd bs=1 seek=102754 count=1 conv=notrunc of=ce_loop.iso
  echo $'\x1c' | dd bs=1 seek=102761 count=1 conv=notrunc of=ce_loop.iso
  # Zeroize the higher valued bytes of the length field
  dd if=/dev/zero bs=1 seek=102755 count=6 conv=notrunc of=ce_loop.iso

This really bad CE entry then looks in the hex dump like:

00019140 :00  7b  01  09  08  08  1c  00  4e  4d  06  01  00  78  43  45
   {   N   M   x   C   E
  102720 : 0 123   1   9   8   8  28   0  78  77   6   1   0 120  67  69

00019150 :1c  01  32  00  00  00  00  00  00  32  4e  01  00  00  00  00
   2   2   N
  102736 :28   1  50   0   0   0   0   0   0  50  78   1   0   0   0   0

00019160 :01  4e  1c  00  00  00  00  00  00  1c  00  00  00  00  00  00
   N
  102752 : 1  78  28   0   0   0   0   0   0  28   0   0   0   0   0   0

(Note: 00019140 is hex, not octal)

--

I will first try to fix libisofs before i upload this gremlin somewhere.

If you want to try in advance, run above shell commands and check whether
a hex editor shows the expected bytes afterwards. (xorriso is supposed to
be reproducible in respect to sizes and locations. Very old versions might
not fulfill that expectation, though.)


Have a nice day :)

Thomas


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: [PATCH v2] Fix possible integer overflow in i386-pc mode with large partitions

2023-01-09 Thread Daniel Kiper
On Wed, Dec 28, 2022 at 05:40:06PM +, Maxim Fomin wrote:
> From f9e2970e5731f13fdc506dbf5c722fd24b20a1aa Mon Sep 17 00:00:00 2001
> From: Maxim Fomin 
> Date: Wed, 28 Dec 2022 20:25:05 +
> Subject: [PATCH v2] Fix possible integer overflow in i386-pc mode with large
>  partitions
>
> The i386-pc mode supports MBR partition scheme
> where maximum partition size is 2 TiB. In case
> of large partitions left shift expression with
> unsigned long int 'length' object may cause
> integer overflow making calculated partition
> size less than true value. This issue is fixed
> by increasing the size of 'length' integer type.
> ---
>  grub-core/kern/fs.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/grub-core/kern/fs.c b/grub-core/kern/fs.c
> index b9508296d..7ad0aaf4e 100644
> --- a/grub-core/kern/fs.c
> +++ b/grub-core/kern/fs.c
> @@ -130,7 +130,7 @@ grub_fs_probe (grub_device_t device)
>  struct grub_fs_block
>  {
>grub_disk_addr_t offset;
> -  unsigned long length;
> +  grub_disk_addr_t length;

Reviewed-by: Daniel Kiper 

Daniel

___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v4 11/19] efi/http: match protocol+hostname of boot url in root_url

2023-01-09 Thread Robbie Harwood
From: Peter Jones 

This lets you write config files that don't know urls.

Signed-off-by: Peter Jones 
Signed-off-by: Robbie Harwood 
---
 grub-core/net/efi/http.c | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/grub-core/net/efi/http.c b/grub-core/net/efi/http.c
index 03750e37b6..87fc02da20 100644
--- a/grub-core/net/efi/http.c
+++ b/grub-core/net/efi/http.c
@@ -3,6 +3,7 @@
 #include 
 #include 
 #include 
+#include 
 
 static void
 http_configure (struct grub_efi_net_device *dev, int prefer_ip6)
@@ -338,6 +339,24 @@ grub_efihttp_open (struct grub_efi_net_device *dev,
   grub_err_t err;
   grub_off_t size = 0;
   char *buf = NULL;
+  char *root_url;
+  grub_efi_ipv6_address_t address;
+  const char *rest;
+
+  if (grub_efi_string_to_ip6_address (file->device->net->server, &address, 
&rest) && *rest == 0)
+root_url = grub_xasprintf ("%s://[%s]", type ? "https" : "http", 
file->device->net->server);
+  else
+root_url = grub_xasprintf ("%s://%s", type ? "https" : "http", 
file->device->net->server);
+  if (root_url)
+{
+  grub_env_unset ("root_url");
+  grub_env_set ("root_url", root_url);
+  grub_free (root_url);
+}
+  else
+{
+  return grub_errno;
+}
 
   err = efihttp_request (dev->http, file->device->net->server, 
file->device->net->name, type, 1, 0);
   if (err != GRUB_ERR_NONE)
-- 
2.39.0


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v4 06/19] bootp: Process DHCPACK packet during HTTP Boot

2023-01-09 Thread Robbie Harwood
From: Michael Chang 

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 obselete 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.

Add 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 
Signed-off-by: Ken Lin 
Signed-off-by: Robbie Harwood 
---
 grub-core/net/bootp.c | 55 +++
 include/grub/net.h|  1 +
 2 files changed, 56 insertions(+)

diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
index c16267fe6a..9f62579c5b 100644
--- a/grub-core/net/bootp.c
+++ b/grub-core/net/bootp.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -506,6 +507,60 @@ grub_net_configure_by_dhcp_ack (const char *name,
   if (opt && opt_len)
 grub_env_set_net_property (name, "rootpath", (const char *) opt, opt_len);
 
+  opt = find_dhcp_option (bp, size, GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER, 
&opt_len);
+  if (opt && opt_len)
+{
+  grub_env_set_net_property (name, "vendor_class_identifier", (const char 
*) opt, opt_len);
+  if (opt && grub_strcmp ((const char *) opt, "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;
+}
+}
+
   opt = find_dhcp_option (bp, size, GRUB_NET_BOOTP_EXTENSIONS_PATH, &opt_len);
   if (opt && opt_len)
 grub_env_set_net_property (name, "extensionspath", (const char *) opt, 
opt_len);
diff --git a/include/grub/net.h b/include/grub/net.h
index fc326ab330..8f541e59b8 100644
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -530,6 +530,7 @@ enum
 GRUB_NET_DHCP_MESSAGE_TYPE = 53,
 GRUB_NET_DHCP_SERVER_IDENTIFIER = 54,
 GRUB_NET_DHCP_PARAMETER_REQUEST_LIST = 55,
+GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER = 60,
 GRUB_NET_BOOTP_CLIENT_ID = 61,
 GRUB_NET_DHCP_TFTP_SERVER_NAME = 66,
 GRUB_NET_DHCP_BOOTFILE_NAME = 67,
-- 
2.39.0


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v4 15/19] Prepend prefix when HTTP path is relative

2023-01-09 Thread Robbie Harwood
From: Stephen Benjamin 

This sets a couple of variables.  With the url http://www.example.com/foo/bar :
http_path: /foo/bar
http_url: http://www.example.com/foo/bar

Resolves: rhbz#1616395
Co-authored-by: Javier Martinez Canillas 
Co-authored-by: Robbie Harwood 
Signed-off-by: Peter Jones 
Signed-off-by: Stephen Benjamin 
Signed-off-by: Javier Martinez Canillas 
Signed-off-by: Robbie Harwood 
---
 grub-core/kern/main.c| 10 -
 grub-core/net/efi/http.c | 85 ++--
 2 files changed, 73 insertions(+), 22 deletions(-)

diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
index e1e6cf7a02..353a62ef1e 100644
--- a/grub-core/kern/main.c
+++ b/grub-core/kern/main.c
@@ -131,12 +131,20 @@ grub_set_prefix_and_root (void)
   if (fwdevice && fwpath)
 {
   char *fw_path;
+  char separator[3] = ")";
 
-  fw_path = grub_xasprintf ("(%s)/%s", fwdevice, fwpath);
+  grub_dprintf ("fw_path", "\n");
+  grub_dprintf ("fw_path", "fwdevice:\"%s\" fwpath:\"%s\"\n", fwdevice, 
fwpath);
+
+  if (!grub_strncmp(fwdevice, "http", 4) && fwpath[0] != '/')
+   grub_strcpy(separator, ")/");
+
+  fw_path = grub_xasprintf ("(%s%s%s", fwdevice, separator, fwpath);
   if (fw_path)
{
  grub_env_set ("fw_path", fw_path);
  grub_env_export ("fw_path");
+ grub_dprintf ("fw_path", "fw_path:\"%s\"\n", fw_path);
  grub_free (fw_path);
}
 }
diff --git a/grub-core/net/efi/http.c b/grub-core/net/efi/http.c
index 87fc02da20..ed0d40bee3 100644
--- a/grub-core/net/efi/http.c
+++ b/grub-core/net/efi/http.c
@@ -8,10 +8,53 @@
 static void
 http_configure (struct grub_efi_net_device *dev, int prefer_ip6)
 {
+  grub_efi_ipv6_address_t address;
   grub_efi_http_config_data_t http_config;
   grub_efi_httpv4_access_point_t httpv4_node;
   grub_efi_httpv6_access_point_t httpv6_node;
   grub_efi_status_t status;
+  int https;
+  char *http_url;
+  const char *rest, *http_server, *http_path = NULL;
+
+  http_server = grub_env_get ("root");
+  https = (grub_strncmp (http_server, "https", 5) == 0) ? 1 : 0;
+
+  /* extract http server + port */
+  if (http_server)
+{
+  http_server = grub_strchr (http_server, ',');
+  if (http_server)
+   http_server++;
+}
+
+  /* fw_path is like (http,192.168.1.1:8000)/httpboot, extract path part */
+  http_path = grub_env_get ("fw_path");
+  if (http_path)
+{
+  http_path = grub_strchr (http_path, ')');
+  if (http_path)
+   {
+ http_path++;
+ grub_env_unset ("http_path");
+ grub_env_set ("http_path", http_path);
+ grub_env_export ("http_path");
+   }
+}
+
+  if (http_server && http_path)
+{
+  if (grub_efi_string_to_ip6_address (http_server, &address, &rest) && 
*rest == 0)
+   http_url = grub_xasprintf ("%s://[%s]%s", https ? "https" : "http", 
http_server, http_path);
+  else
+   http_url = grub_xasprintf ("%s://%s%s", https ? "https" : "http", 
http_server, http_path);
+  if (http_url)
+   {
+ grub_env_unset ("http_url");
+ grub_env_set ("http_url", http_url);
+ grub_free (http_url);
+   }
+}
 
   grub_efi_http_t *http = dev->http;
 
@@ -339,32 +382,32 @@ grub_efihttp_open (struct grub_efi_net_device *dev,
   grub_err_t err;
   grub_off_t size = 0;
   char *buf = NULL;
-  char *root_url;
-  grub_efi_ipv6_address_t address;
-  const char *rest;
+  char *file_name = NULL;
+  const char *http_path;
 
-  if (grub_efi_string_to_ip6_address (file->device->net->server, &address, 
&rest) && *rest == 0)
-root_url = grub_xasprintf ("%s://[%s]", type ? "https" : "http", 
file->device->net->server);
-  else
-root_url = grub_xasprintf ("%s://%s", type ? "https" : "http", 
file->device->net->server);
-  if (root_url)
-{
-  grub_env_unset ("root_url");
-  grub_env_set ("root_url", root_url);
-  grub_free (root_url);
-}
-  else
-{
+  /* If path is relative, prepend http_path */
+  http_path = grub_env_get ("http_path");
+  if (http_path && file->device->net->name[0] != '/') {
+file_name = grub_xasprintf ("%s/%s", http_path, file->device->net->name);
+if (!file_name)
   return grub_errno;
+  }
+
+  err = efihttp_request (dev->http, file->device->net->server,
+file_name ? file_name : file->device->net->name, type, 
1, 0);
+  if (err != GRUB_ERR_NONE)
+{
+  grub_free (file_name);
+  return err;
 }
 
-  err = efihttp_request (dev->http, file->device->net->server, 
file->device->net->name, type, 1, 0);
+  err = efihttp_request (dev->http, file->device->net->server,
+file_name ? file_name : file->device->net->name, type, 
0, &size);
+  grub_free (file_name);
   if (err != GRUB_ERR_NONE)
-return err;
-
-  err = efihttp_request (dev->http, file->device->net->server, 
file->device->net->name, type, 0, &size);
-  if (err != GRUB_ERR_NONE)
-return err;
+{
+  return

[PATCH v4 04/19] efinet: add structures for PXE messages

2023-01-09 Thread Robbie Harwood
From: Michael Chang 

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.

Augment existing structures to represent this, and make them agnostic
between ipv4 and ipv6.

Signed-off-by: Michael Chang 
Signed-off-by: Ken Lin 
Co-authored-by: Robbie Harwood 
Signed-off-by: Robbie Harwood 
---
 grub-core/net/drivers/efi/efinet.c |  2 +
 include/grub/efi/api.h | 71 ++
 2 files changed, 46 insertions(+), 27 deletions(-)

diff --git a/grub-core/net/drivers/efi/efinet.c 
b/grub-core/net/drivers/efi/efinet.c
index 75bbfd1bbf..a10383bb6d 100644
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -426,6 +426,8 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char 
**device,
  grub_print_error ();
if (device && path)
  grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path);
+   if (grub_errno)
+ grub_print_error ();
   }
 else
   {
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index 3fa65c3499..e6e2056a0d 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -1565,31 +1565,6 @@ typedef union
   grub_efi_pxe_dhcpv6_packet_t dhcpv6;
 } grub_efi_pxe_packet_t;
 
-#define GRUB_EFI_PXE_MAX_IPCNT 8
-#define GRUB_EFI_PXE_MAX_ARP_ENTRIES 8
-#define GRUB_EFI_PXE_MAX_ROUTE_ENTRIES 8
-
-typedef struct grub_efi_pxe_ip_filter
-{
-  grub_efi_uint8_t filters;
-  grub_efi_uint8_t ip_count;
-  grub_efi_uint16_t reserved;
-  grub_efi_ip_address_t ip_list[GRUB_EFI_PXE_MAX_IPCNT];
-} grub_efi_pxe_ip_filter_t;
-
-typedef struct grub_efi_pxe_arp_entry
-{
-  grub_efi_ip_address_t ip_addr;
-  grub_efi_mac_address_t mac_addr;
-} grub_efi_pxe_arp_entry_t;
-
-typedef struct grub_efi_pxe_route_entry
-{
-  grub_efi_ip_address_t ip_addr;
-  grub_efi_ip_address_t subnet_mask;
-  grub_efi_ip_address_t gateway_addr;
-} grub_efi_pxe_route_entry_t;
-
 typedef struct grub_efi_pxe_icmp_error
 {
   grub_efi_uint8_t type;
@@ -1615,6 +1590,48 @@ typedef struct grub_efi_pxe_tftp_error
   grub_efi_char8_t error_string[127];
 } grub_efi_pxe_tftp_error_t;
 
+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_efi_pxe_ip_filter
+{
+  grub_efi_uint8_t filters;
+  grub_efi_uint8_t ip_count;
+  grub_efi_uint16_t reserved;
+  grub_efi_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_efi_boolean_t started;
@@ -1646,9 +1663,9 @@ typedef struct grub_efi_pxe_mode
   grub_efi_pxe_packet_t pxe_bis_reply;
   grub_efi_pxe_ip_filter_t ip_filter;
   grub_efi_uint32_t arp_cache_entries;
-  grub_efi_pxe_arp_entry_t arp_cache[GRUB_EFI_PXE_MAX_ARP_ENTRIES];
+  grub_efi_pxe_arp_entry_t arp_cache[GRUB_EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES];
   grub_efi_uint32_t route_table_entries;
-  grub_efi_pxe_route_entry_t route_table[GRUB_EFI_PXE_MAX_ROUTE_ENTRIES];
+  grub_efi_pxe_route_entry_t 
route_table[GRUB_EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES];
   grub_efi_pxe_icmp_error_t icmp_error;
   grub_efi_pxe_tftp_error_t tftp_error;
 } grub_efi_pxe_mode_t;
-- 
2.39.0


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v4 00/19] UEFI networking support including ipv6 + dhcpv6

2023-01-09 Thread Robbie Harwood
This series is an omnibus of changes we carry for networking that has
accumulated since at least 2015.  While most of it did not receive review when
previously posted, one did, so I'm using that as an excuse to call this v4.

At the start, this includes a proposed revert of
ac8a37dda0eabdd80506bebe4fb9a5a9fd227935 ("net/http: Allow use of non-standard
TCP/IP ports").  In 2016, a different approach to this more in keeping with
the way port numbers are typically specified was posted on-list:
https://lists.gnu.org/archive/html/grub-devel/2016-04/msg00071.html [1]

At least Debian, Red Hat, SUSE, and Ubuntu have carried it since then, which
means that code in the wild expects this syntax, not the other syntax.
(Others may have as well - I didn't do an exhaustive check - but hopefully
that's enough to convey the point.)

At this point, the division of code between patches is mostly organic.  I've
folded bugfixes into their original commits and moved a few other things
around, so while this doesn't exactly match the division in the rhboot tree,
it does match the code.  At this version, the only code differences are style
adjustments and rebasing around the vlan changes that merged since 2.06.

Be well,
--Robbie

1: For the curious, while the strtoull patch mentioned there was also not
   taken, the issue is no longer present.

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

Ian Page Hands (1):
  efinet: Add DHCP proxy support

Javier Martinez Canillas (3):
  efi/http: Enclose literal IPv6 addresses in square brackets
  http: Prepend prefix when the HTTP path is relative
  normal/main: Discover the device to read the config from as a fallback

Mark Salter (1):
  use fw_path prefix when fallback searching for grub config

Michael Chang (6):
  efinet: add structures for PXE messages
  grub.texi: Add net_bootp6 doumentation
  bootp: Process DHCPACK packet during HTTP Boot
  efinet Configure network from UEFI device path
  efinet: set DNS server from UEFI protocol
  Support UEFI networking protocols

Paulo Flabiano Smorigo (1):
  Add fw_path variable to detect config file on efi

Peter Jones (4):
  efinet + bootp: add net_bootp6 command supporting dhcpv6
  efinet: also use the firmware acceleration for http
  efi/http: match protocol+hostname of boot url in root_url
  Try mac/guid/etc before grub.cfg on tftp config files

Robbie Harwood (1):
  Revert "net/http: Allow use of non-standard TCP/IP ports"

Stephen Benjamin (1):
  Prepend prefix when HTTP path is relative

 docs/grub.texi |   50 +-
 grub-core/Makefile.core.def|   12 +
 grub-core/io/bufio.c   |2 +-
 grub-core/kern/efi/efi.c   |   96 +-
 grub-core/kern/ieee1275/init.c |   28 +-
 grub-core/kern/main.c  |   22 +-
 grub-core/net/bootp.c  |  965 ++-
 grub-core/net/drivers/efi/efinet.c |  521 +-
 grub-core/net/efi/dhcp.c   |  357 +++
 grub-core/net/efi/efi_netfs.c  |   57 ++
 grub-core/net/efi/http.c   |  490 ++
 grub-core/net/efi/ip4_config.c |  417 
 grub-core/net/efi/ip6_config.c |  423 +
 grub-core/net/efi/net.c| 1416 
 grub-core/net/efi/pxe.c|  354 +++
 grub-core/net/http.c   |   76 +-
 grub-core/net/ip.c |   39 +
 grub-core/net/net.c|  235 -
 grub-core/net/tftp.c   |   10 +-
 grub-core/normal/main.c|  149 ++-
 include/grub/efi/api.h |  397 +++-
 include/grub/efi/dhcp.h|  347 +++
 include/grub/efi/http.h|  215 +
 include/grub/net.h |   81 ++
 include/grub/net/efi.h |  144 +++
 util/grub-mknetdir.c   |   23 +-
 26 files changed, 6736 insertions(+), 190 deletions(-)
 create mode 100644 grub-core/net/efi/dhcp.c
 create mode 100644 grub-core/net/efi/efi_netfs.c
 create mode 100644 grub-core/net/efi/http.c
 create mode 100644 grub-core/net/efi/ip4_config.c
 create mode 100644 grub-core/net/efi/ip6_config.c
 create mode 100644 grub-core/net/efi/net.c
 create mode 100644 grub-core/net/efi/pxe.c
 create mode 100644 include/grub/efi/dhcp.h
 create mode 100644 include/grub/efi/http.h
 create mode 100644 include/grub/net/efi.h

-- 
2.39.0


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v4 19/19] efinet: Add DHCP proxy support

2023-01-09 Thread Robbie Harwood
From: Ian Page Hands 

If a proxyDHCP configuration is used, the server name, server IP and
boot file values should be taken from the DHCP proxy offer instead of
the DHCP server ack packet.

Signed-off-by: Ian Page Hands 
Co-authored-by: Robbie Harwood 
Signed-off-by: Robbie Harwood 
---
 grub-core/net/drivers/efi/efinet.c | 27 +--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/grub-core/net/drivers/efi/efinet.c 
b/grub-core/net/drivers/efi/efinet.c
index d4ae865b6f..fc8d7ef196 100644
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -863,10 +863,33 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char 
**device,
 else
   {
grub_dprintf ("efinet", "using ipv4 and dhcp\n");
+
+struct grub_net_bootp_packet *dhcp_ack = (void *) &pxe_mode->dhcp_ack;
+
+if (pxe_mode->proxy_offer_received)
+  {
+grub_dprintf ("efinet", "proxy offer receive");
+struct grub_net_bootp_packet *proxy_offer = (void *) 
&pxe_mode->proxy_offer;
+
+if (proxy_offer && dhcp_ack->boot_file[0] == '\0')
+  {
+grub_dprintf ("efinet", "setting values from proxy offer");
+/*
+ * Here we got a proxy offer and the dhcp_ack has a nil
+ * boot_file Copy the proxy DHCP offer details into the
+ * bootp_packet we are sending forward as they are the deatils
+ * we need.
+ */
+*dhcp_ack->server_name = *proxy_offer->server_name;
+*dhcp_ack->boot_file = *proxy_offer->boot_file;
+dhcp_ack->server_ip = proxy_offer->server_ip;
+  }
+  }
+
inter = grub_net_configure_by_dhcp_ack (card->name, card, 0,
 (struct grub_net_bootp_packet 
*)
-packet_buf,
-packet_bufsz,
+&pxe_mode->dhcp_ack,
+sizeof (pxe_mode->dhcp_ack),
 1, device, path);
grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path);
   }
-- 
2.39.0


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v4 01/19] Revert "net/http: Allow use of non-standard TCP/IP ports"

2023-01-09 Thread Robbie Harwood
This reverts commit ac8a37dda0eabdd80506bebe4fb9a5a9fd227935.

Signed-off-by: Robbie Harwood 
---
 docs/grub.texi   | 33 -
 grub-core/net/http.c | 40 ++--
 2 files changed, 2 insertions(+), 71 deletions(-)

diff --git a/docs/grub.texi b/docs/grub.texi
index 50c811a88e..ed295dabd2 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -3053,39 +3053,6 @@ environment variable @samp{net_default_server} is used.
 Before using the network drive, you must initialize the network.
 @xref{Network}, for more information.
 
-For the @samp{http} network protocol, @code{@var{server}} may specify a
-port number other than the default value of @samp{80}. The server name
-and port number are separated by either @samp{,} or @samp{:}.
-For IPv6 addresses, the server name and port number may only be separated
-by @samp{,}.
-
-@itemize @bullet
-@item
-@code{(http,@var{server},@var{port})}
-
-@item
-@code{(http,@var{server}:@var{port})}
-@end itemize
-
-These examples all reference an @samp{http} server at address
-@samp{192.0.2.1} listening on the non-standard port of @samp{3000}.
-In these examples, the DNS name @samp{grub.example.com} is resolved
-to @samp{192.0.2.1}.
-
-@example
-(http,grub.example.com,3000)
-(http,grub.example.com:3000)
-(http,192.0.2.1,3000)
-(http,192.0.2.1:3000)
-@end example
-
-Referencing an @samp{http} server over IPv6 on the non-standard
-port of @samp{3000} would look like this:
-
-@example
-(http,2001:db8::1,3000)
-@end example
-
 If you boot GRUB from a CD-ROM, @samp{(cd)} is available. @xref{Making
 a GRUB bootable CD-ROM}, for details.
 
diff --git a/grub-core/net/http.c b/grub-core/net/http.c
index 9291a13e2d..d67cad4829 100644
--- a/grub-core/net/http.c
+++ b/grub-core/net/http.c
@@ -318,10 +318,6 @@ 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_name;
-  char *port_string;
-  const char *port_string_end;
-  unsigned long port_number;
 
   nb = grub_netbuff_alloc (GRUB_NET_TCP_RESERVE_SIZE
   + sizeof ("GET ") - 1
@@ -400,42 +396,10 @@ http_establish (struct grub_file *file, grub_off_t 
offset, int initial)
   grub_netbuff_put (nb, 2);
   grub_memcpy (ptr, "\r\n", 2);
 
-  port_string = grub_strrchr (file->device->net->server, ',');
-  if (port_string == NULL)
-{
-  /* If ",port" is not found in the http server string, look for ":port". 
*/
-  port_string = grub_strrchr (file->device->net->server, ':');
-  /* For IPv6 addresses, the ":port" syntax is not supported and ",port" 
must be used. */
-  if (port_string != NULL && grub_strchr (file->device->net->server, ':') 
!= port_string)
- port_string = NULL;
-}
-  if (port_string != NULL)
-{
-  port_number = grub_strtoul (port_string + 1, &port_string_end, 10);
-  if (*(port_string + 1) == '\0' || *port_string_end != '\0')
- return grub_error (GRUB_ERR_BAD_NUMBER, N_("non-numeric or invalid 
port number `%s'"), port_string + 1);
-  if (port_number == 0 || port_number > 65535)
- return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("port number `%s' not in 
the range of 1 to 65535"), port_string + 1);
-
-  server_name = grub_strdup (file->device->net->server);
-  if (server_name == NULL)
- return grub_errno;
-  server_name[port_string - file->device->net->server] = '\0';
-}
-  else
-{
-  port_number = HTTP_PORT;
-  server_name = file->device->net->server;
-}
-
-  data->sock = grub_net_tcp_open (server_name,
- port_number, http_receive,
+  data->sock = grub_net_tcp_open (file->device->net->server,
+ HTTP_PORT, http_receive,
  http_err, NULL,
  file);
-
-  if (server_name != file->device->net->server)
-  grub_free (server_name);
-
   if (!data->sock)
 {
   grub_netbuff_free (nb);
-- 
2.39.0


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v4 07/19] efinet Configure network from UEFI device path

2023-01-09 Thread Robbie Harwood
From: Michael Chang 

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 for Uniform Resource Identifiers (URI) Device Path

grub-core/net/drivers/efi/efinet.c:

Check if PXE Base Code is available.  If not, 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 fed
into the same DHCP packet processing functions to ensure the network
interface is set up the same way it used to be.

Signed-off-by: Michael Chang 
Signed-off-by: Ken Lin 
Signed-off-by: Robbie Harwood 
---
 grub-core/net/drivers/efi/efinet.c | 278 +++--
 include/grub/efi/api.h |  11 ++
 2 files changed, 274 insertions(+), 15 deletions(-)

diff --git a/grub-core/net/drivers/efi/efinet.c 
b/grub-core/net/drivers/efi/efinet.c
index a10383bb6d..4cbd213cf3 100644
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
@@ -344,6 +345,225 @@ 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);
+  if (!ddp)
+return NULL;
+
+  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)
+{
+  grub_free (ddp);
+  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;
+

[PATCH v4 16/19] efi/http: Enclose literal IPv6 addresses in square brackets

2023-01-09 Thread Robbie Harwood
From: Javier Martinez Canillas 

According to RFC 2732 (https://www.ietf.org/rfc/rfc2732.txt), literal IPv6
addresses must be enclosed in square brackets. But GRUB currently does not
do this and is causing HTTP servers to send Bad Request (400) responses.

For example, the following is the HTTP stream when fetching a config file:

HEAD /EFI/BOOT/grub.cfg HTTP/1.1
Host: 2000:dead:beef:a::1
Accept: */*
User-Agent: UefiHttpBoot/1.0

HTTP/1.1 400 Bad Request
Date: Thu, 05 Mar 2020 14:46:02 GMT
Server: Apache/2.4.41 (Fedora) OpenSSL/1.1.1d
Connection: close
Content-Type: text/html; charset=iso-8859-1

and after enclosing the IPv6 address the HTTP request is successful:

HEAD /EFI/BOOT/grub.cfg HTTP/1.1
Host: [2000:dead:beef:a::1]
Accept: */*
User-Agent: UefiHttpBoot/1.0

HTTP/1.1 200 OK
Date: Thu, 05 Mar 2020 14:48:04 GMT
Server: Apache/2.4.41 (Fedora) OpenSSL/1.1.1d
Last-Modified: Thu, 27 Feb 2020 17:45:58 GMT
ETag: "206-59f924b24b1da"
Accept-Ranges: bytes
Content-Length: 518

Resolves: rhbz#1732765

Signed-off-by: Javier Martinez Canillas 
Signed-off-by: Robbie Harwood 
---
 grub-core/net/efi/http.c | 37 -
 1 file changed, 28 insertions(+), 9 deletions(-)

diff --git a/grub-core/net/efi/http.c b/grub-core/net/efi/http.c
index ed0d40bee3..e485c27ee1 100644
--- a/grub-core/net/efi/http.c
+++ b/grub-core/net/efi/http.c
@@ -147,13 +147,7 @@ efihttp_request (grub_efi_http_t *http, char *server, char 
*name, int use_https,
   grub_efi_status_t status;
   grub_efi_boot_services_t *b = grub_efi_system_table->boot_services;
   char *url = NULL;
-
-  request_headers[0].field_name = (grub_efi_char8_t *) "Host";
-  request_headers[0].field_value = (grub_efi_char8_t *) server;
-  request_headers[1].field_name = (grub_efi_char8_t *) "Accept";
-  request_headers[1].field_value = (grub_efi_char8_t *) "*/*";
-  request_headers[2].field_name = (grub_efi_char8_t *) "User-Agent";
-  request_headers[2].field_value = (grub_efi_char8_t *) "UefiHttpBoot/1.0";
+  char *hostname = NULL;
 
   {
 grub_efi_ipv6_address_t address;
@@ -163,9 +157,24 @@ efihttp_request (grub_efi_http_t *http, char *server, char 
*name, int use_https,
 const char *protocol = (use_https == 1) ? "https" : "http";
 
 if (grub_efi_string_to_ip6_address (server, &address, &rest) && *rest == 0)
-  url = grub_xasprintf ("%s://[%s]%s", protocol, server, name);
+  {
+hostname = grub_xasprintf ("[%s]", server);
+if (!hostname)
+  return GRUB_ERR_OUT_OF_MEMORY;
+
+server = hostname;
+
+url = grub_xasprintf ("%s://%s%s", protocol, server, name);
+if (!url)
+  {
+grub_free (hostname);
+return GRUB_ERR_OUT_OF_MEMORY;
+  }
+  }
 else
-  url = grub_xasprintf ("%s://%s%s", protocol, server, name);
+  {
+url = grub_xasprintf ("%s://%s%s", protocol, server, name);
+  }
 
 if (!url)
   {
@@ -190,6 +199,13 @@ efihttp_request (grub_efi_http_t *http, char *server, char 
*name, int use_https,
 request_data.url = ucs2_url;
   }
 
+  request_headers[0].field_name = (grub_efi_char8_t *) "Host";
+  request_headers[0].field_value = (grub_efi_char8_t *) server;
+  request_headers[1].field_name = (grub_efi_char8_t *) "Accept";
+  request_headers[1].field_value = (grub_efi_char8_t *) "*/*";
+  request_headers[2].field_name = (grub_efi_char8_t *) "User-Agent";
+  request_headers[2].field_value = (grub_efi_char8_t *) "UefiHttpBoot/1.0";
+
   request_data.method = (headeronly > 0) ? GRUB_EFI_HTTPMETHODHEAD : 
GRUB_EFI_HTTPMETHODGET;
 
   request_message.data.request = &request_data;
@@ -219,6 +235,9 @@ efihttp_request (grub_efi_http_t *http, char *server, char 
*name, int use_https,
 
   status = efi_call_2 (http->request, http, &request_token);
 
+  if (hostname)
+grub_free (hostname);
+
   if (status != GRUB_EFI_SUCCESS)
 {
   efi_call_1 (b->close_event, request_token.event);
-- 
2.39.0


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v4 12/19] Add fw_path variable to detect config file on efi

2023-01-09 Thread Robbie Harwood
From: Paulo Flabiano Smorigo 

This patch makes grub look for its config file on efi where the app was
found.

Resolves: rhbz#857936, rhbz#1616395
Co-authored-by: Matthew Garrett
Co-authored-by: Javier Martinez Canillas 
Co-authored-by: Robbie Harwood 
Signed-off-by: Paulo Flabiano Smorigo 
Signed-off-by: Javier Martinez Canillas 
Signed-off-by: Robbie Harwood 
---
 grub-core/kern/main.c   | 14 +++---
 grub-core/normal/main.c | 25 -
 2 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
index 731c07c290..e1e6cf7a02 100644
--- a/grub-core/kern/main.c
+++ b/grub-core/kern/main.c
@@ -128,16 +128,16 @@ grub_set_prefix_and_root (void)
 
   grub_machine_get_bootlocation (&fwdevice, &fwpath);
 
-  if (fwdevice)
+  if (fwdevice && fwpath)
 {
-  char *cmdpath;
+  char *fw_path;
 
-  cmdpath = grub_xasprintf ("(%s)%s", fwdevice, fwpath ? : "");
-  if (cmdpath)
+  fw_path = grub_xasprintf ("(%s)/%s", fwdevice, fwpath);
+  if (fw_path)
{
- grub_env_set ("cmdpath", cmdpath);
- grub_env_export ("cmdpath");
- grub_free (cmdpath);
+ grub_env_set ("fw_path", fw_path);
+ grub_env_export ("fw_path");
+ grub_free (fw_path);
}
 }
 
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index bd44310005..a557ba5c9c 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -320,7 +320,30 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ 
((unused)),
   /* Guess the config filename. It is necessary to make CONFIG static,
 so that it won't get broken by longjmp.  */
   char *config;
-  const char *prefix;
+  const char *prefix, *fw_path;
+
+  fw_path = grub_env_get ("fw_path");
+  if (fw_path)
+   {
+ config = grub_xasprintf ("%s/grub.cfg", fw_path);
+ if (config)
+   {
+ grub_file_t file;
+
+ file = grub_file_open (config, GRUB_FILE_TYPE_CONFIG);
+ if (file)
+   {
+ grub_file_close (file);
+ grub_enter_normal_mode (config);
+   }
+  else
+{
+  /* Ignore all errors.  */
+  grub_errno = 0;
+}
+ grub_free (config);
+   }
+   }
 
   prefix = grub_env_get ("prefix");
   if (prefix)
-- 
2.39.0


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v4 03/19] efinet + bootp: add net_bootp6 command supporting dhcpv6

2023-01-09 Thread Robbie Harwood
From: Peter Jones 

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

Signed-off-by: Peter Jones 
Co-authored-by: Michael Chang 
Signed-off-by: Michael Chang 
Signed-off-by: Ken Lin 
Co-authored-by: Robbie Harwood 
Signed-off-by: Robbie Harwood 
---
 grub-core/net/bootp.c  | 910 -
 grub-core/net/drivers/efi/efinet.c |  52 +-
 grub-core/net/ip.c |  39 ++
 grub-core/net/net.c|  72 +++
 grub-core/net/tftp.c   |   3 +
 include/grub/efi/api.h | 129 +++-
 include/grub/net.h |  79 +++
 7 files changed, 1267 insertions(+), 17 deletions(-)

diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
index 7d31dba970..c16267fe6a 100644
--- a/grub-core/net/bootp.c
+++ b/grub-core/net/bootp.c
@@ -24,6 +24,98 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+
+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;
+}
 
 struct grub_dhcp_discover_options
 {
@@ -608,6 +700,583 @@ out:
   return err;
 }
 
+/* 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_ad

[PATCH v4 05/19] grub.texi: Add net_bootp6 doumentation

2023-01-09 Thread Robbie Harwood
From: Michael Chang 

Update grub documentation for net_bootp6 command.

Signed-off-by: Michael Chang 
Signed-off-by: Ken Lin 
Signed-off-by: Robbie Harwood 
---
 docs/grub.texi | 17 +
 1 file changed, 17 insertions(+)

diff --git a/docs/grub.texi b/docs/grub.texi
index ed295dabd2..63646d6996 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -5720,6 +5720,7 @@ Note: The command is not allowed when lockdown is 
enforced (@pxref{Lockdown}).
 * net_add_dns:: Add a DNS server
 * net_add_route::   Add routing entry
 * net_bootp::   Perform a bootp/DHCP 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
@@ -5845,6 +5846,22 @@ Sets environment variable 
@samp{net_}@var{}@samp{_boot_file}
 
 @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_get_dhcp_option
 @subsection net_get_dhcp_option
-- 
2.39.0


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v4 13/19] use fw_path prefix when fallback searching for grub config

2023-01-09 Thread Robbie Harwood
From: Mark Salter 

When PXE booting via UEFI firmware, grub was searching for grub.cfg in
the fw_path directory where the grub application was found.  If that
didn't exist, a fallback search would look for config file names based
on MAC and IP address.  However, the search would look in the prefix
directory which may not be the same fw_path.  This patch changes that
behavior to use the fw_path directory for the fallback search.  Only if
fw_path is NULL will the prefix directory be searched.

Signed-off-by: Mark Salter 
Signed-off-by: Robbie Harwood 
---
 grub-core/normal/main.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index a557ba5c9c..dfdfd56e06 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -322,7 +322,7 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ 
((unused)),
   char *config;
   const char *prefix, *fw_path;
 
-  fw_path = grub_env_get ("fw_path");
+  prefix = fw_path = grub_env_get ("fw_path");
   if (fw_path)
{
  config = grub_xasprintf ("%s/grub.cfg", fw_path);
@@ -345,7 +345,8 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ 
((unused)),
}
}
 
-  prefix = grub_env_get ("prefix");
+  if (!prefix)
+prefix = grub_env_get ("prefix");
   if (prefix)
 {
   grub_size_t config_len;
-- 
2.39.0


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v4 10/19] efinet: also use the firmware acceleration for http

2023-01-09 Thread Robbie Harwood
From: Peter Jones 

Signed-off-by: Peter Jones 
Signed-off-by: Robbie Harwood 
---
 grub-core/net/efi/net.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/grub-core/net/efi/net.c b/grub-core/net/efi/net.c
index 012dc654c5..9ea7ed141f 100644
--- a/grub-core/net/efi/net.c
+++ b/grub-core/net/efi/net.c
@@ -1307,7 +1307,10 @@ grub_efi_net_boot_from_https (void)
  && (subtype == GRUB_EFI_URI_DEVICE_PATH_SUBTYPE))
{
  grub_efi_uri_device_path_t *uri_dp = (grub_efi_uri_device_path_t *) 
dp;
- return (grub_strncmp ((const char*) uri_dp->uri, "https://";, sizeof 
("https://";) - 1) == 0) ? 1 : 0;
+
+ grub_dprintf ("efinet", "url:%s\n", (const char *) uri_dp->uri);
+ return (grub_strncmp ((const char *) uri_dp->uri, "https://";, sizeof 
("https://";) - 1) == 0 ||
+ grub_strncmp ((const char *) uri_dp->uri, "http://";, sizeof 
("http://";) - 1) == 0);
}
 
   if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
-- 
2.39.0


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v4 02/19] net: read bracketed ipv6 addrs and port numbers

2023-01-09 Thread Robbie Harwood
From: Aaron Miller 

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.

Signed-off-by: Aaron Miller 
Co-authored-by: Peter Jones 
Signed-off-by: Peter Jones 
Signed-off-by: Robbie Harwood 
---
 grub-core/net/http.c | 25 ++---
 grub-core/net/net.c  | 87 +---
 grub-core/net/tftp.c |  7 +++-
 include/grub/net.h   |  1 +
 4 files changed, 109 insertions(+), 11 deletions(-)

diff --git a/grub-core/net/http.c b/grub-core/net/http.c
index d67cad4829..e76c0e4b62 100644
--- a/grub-core/net/http.c
+++ b/grub-core/net/http.c
@@ -295,7 +295,9 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ 
((unused)),
  nb2 = grub_netbuff_alloc (data->chunk_rem);
  if (!nb2)
return grub_errno;
- grub_netbuff_put (nb2, data->chunk_rem);
+ err = grub_netbuff_put (nb2, data->chunk_rem);
+ if (err)
+   return grub_errno;
  grub_memcpy (nb2->data, nb->data, data->chunk_rem);
  if (file->device->net->packs.count >= 20)
{
@@ -318,12 +320,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 (":XX")
   + sizeof ("\r\nUser-Agent: " PACKAGE_STRING
 "\r\n") - 1
   + sizeof ("Range: bytes="
@@ -362,7 +366,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);
@@ -371,6 +375,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 (":XX"),
+ ":%d",
+ port);
+}
+
   ptr = nb->tail;
   err = grub_netbuff_put (nb,
  sizeof ("\r\nUser-Agent: " PACKAGE_STRING "\r\n")
@@ -396,8 +409,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, NULL,
  file);
   if (!data->sock)
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
index 7046dc5789..c7f4fb6a6f 100644
--- a/grub-core/net/net.c
+++ b/grub-core/net/net.c
@@ -443,6 +443,13 @@ 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;
@@ -481,6 +488,8 @@ 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;
@@ -1319,8 +1328,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)
 {
@@ -1358,6 +1369,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;
+   }
+ 

[PATCH v4 08/19] efinet: set DNS server from UEFI protocol

2023-01-09 Thread Robbie Harwood
From: Michael Chang 

In the URI device path node, any name rather 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, 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 
Signed-off-by: Ken Lin 
Signed-off-by: Robbie Harwood 
---
 grub-core/net/drivers/efi/efinet.c | 160 +
 include/grub/efi/api.h |  77 ++
 2 files changed, 237 insertions(+)

diff --git a/grub-core/net/drivers/efi/efinet.c 
b/grub-core/net/drivers/efi/efinet.c
index 4cbd213cf3..5bc1e15ffa 100644
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -33,6 +33,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,
@@ -345,6 +347,122 @@ 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);
+  ret

[PATCH v4 14/19] Try mac/guid/etc before grub.cfg on tftp config files

2023-01-09 Thread Robbie Harwood
From: Peter Jones 

Signed-off-by: Peter Jones 
Signed-off-by: Robbie Harwood 
---
 grub-core/kern/ieee1275/init.c |  28 +++
 grub-core/net/net.c|   2 +-
 grub-core/normal/main.c| 129 +
 3 files changed, 82 insertions(+), 77 deletions(-)

diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
index 2adf4fdfc0..f1c3dff508 100644
--- a/grub-core/kern/ieee1275/init.c
+++ b/grub-core/kern/ieee1275/init.c
@@ -116,23 +116,25 @@ grub_machine_get_bootlocation (char **device, char **path)
   grub_free (canon);
 }
   else
-*device = grub_ieee1275_encode_devname (bootpath);
-  grub_free (type);
-
-  filename = grub_ieee1275_get_filename (bootpath);
-  if (filename)
 {
-  char *lastslash = grub_strrchr (filename, '\\');
-
-  /* Truncate at last directory.  */
-  if (lastslash)
+  filename = grub_ieee1275_get_filename (bootpath);
+  if (filename)
 {
- *lastslash = '\0';
- grub_translate_ieee1275_path (filename);
+  char *lastslash = grub_strrchr (filename, '\\');
 
- *path = filename;
-   }
+  /* Truncate at last directory.  */
+  if (lastslash)
+{
+  *lastslash = '\0';
+  grub_translate_ieee1275_path (filename);
+
+  *path = filename;
+}
+}
+  *device = grub_ieee1275_encode_devname (bootpath);
 }
+
+  grub_free (type);
   grub_free (bootpath);
 }
 
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
index 49a94b97c9..6a1a09a1a3 100644
--- a/grub-core/net/net.c
+++ b/grub-core/net/net.c
@@ -2083,7 +2083,7 @@ grub_net_search_config_file (char *config)
   /* Remove the remaining minus sign at the end. */
   config[config_len] = '\0';
 
-  return GRUB_ERR_NONE;
+  return GRUB_ERR_FILE_NOT_FOUND;
 }
 
 static struct grub_preboot *fini_hnd;
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index dfdfd56e06..58d3dcee8d 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -310,76 +310,79 @@ grub_enter_normal_mode (const char *config)
   grub_boot_time ("Exiting normal mode");
 }
 
+static grub_err_t
+grub_try_normal (const char *variable)
+{
+char *config;
+const char *prefix;
+grub_err_t err = GRUB_ERR_FILE_NOT_FOUND;
+const char *net_search_cfg;
+int disable_net_search = 0;
+
+prefix = grub_env_get (variable);
+if (!prefix)
+  return GRUB_ERR_FILE_NOT_FOUND;
+
+net_search_cfg = grub_env_get ("feature_net_search_cfg");
+if (net_search_cfg && net_search_cfg[0] == 'n')
+  disable_net_search = 1;
+
+if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0 &&
+!disable_net_search)
+  {
+   grub_size_t config_len;
+   config_len = grub_strlen (prefix) +
+ sizeof ("/grub.cfg-----");
+   config = grub_malloc (config_len);
+
+   if (! config)
+ return GRUB_ERR_FILE_NOT_FOUND;
+
+   grub_snprintf (config, config_len, "%s/grub.cfg", prefix);
+   err = grub_net_search_config_file (config);
+  }
+
+if (err != GRUB_ERR_NONE)
+  {
+   config = grub_xasprintf ("%s/grub.cfg", prefix);
+   if (config)
+ {
+   grub_file_t file;
+   file = grub_file_open (config, GRUB_FILE_TYPE_CONFIG);
+   if (file)
+ {
+   grub_file_close (file);
+   err = GRUB_ERR_NONE;
+ }
+ }
+  }
+
+if (err == GRUB_ERR_NONE)
+  grub_enter_normal_mode (config);
+
+grub_errno = 0;
+grub_free (config);
+return err;
+}
+
 /* Enter normal mode from rescue mode.  */
 static grub_err_t
 grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
 int argc, char *argv[])
 {
-  if (argc == 0)
-{
-  /* Guess the config filename. It is necessary to make CONFIG static,
-so that it won't get broken by longjmp.  */
-  char *config;
-  const char *prefix, *fw_path;
-
-  prefix = fw_path = grub_env_get ("fw_path");
-  if (fw_path)
-   {
- config = grub_xasprintf ("%s/grub.cfg", fw_path);
- if (config)
-   {
- grub_file_t file;
-
- file = grub_file_open (config, GRUB_FILE_TYPE_CONFIG);
- if (file)
-   {
- grub_file_close (file);
- grub_enter_normal_mode (config);
-   }
-  else
-{
-  /* Ignore all errors.  */
-  grub_errno = 0;
-}
- grub_free (config);
-   }
-   }
-
-  if (!prefix)
-prefix = grub_env_get ("prefix");
-  if (prefix)
-{
-  grub_size_t config_len;
-  int disable_net_search = 0;
-  const char *net_search_cfg;
-
-  config_len = grub_strlen (prefix) +
-   sizeof 
("/grub.cfg---X

[PATCH v4 17/19] http: Prepend prefix when the HTTP path is relative

2023-01-09 Thread Robbie Harwood
From: Javier Martinez Canillas 

There are two different HTTP drivers that can be used when requesting an
HTTP resource: the efi/http that uses the EFI_HTTP_PROTOCOL and the http
that uses GRUB's HTTP and TCP/IP implementation.

The efi/http driver appends a prefix that is defined in the variable
http_path, but the http driver doesn't.  So using this driver and
attempting to fetch a resource using a relative path fails.  Match the
behavior of efi/http.

Signed-off-by: Javier Martinez Canillas 
Co-authored-by: Robbie Harwood 
Signed-off-by: Robbie Harwood 
---
 grub-core/net/http.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/grub-core/net/http.c b/grub-core/net/http.c
index f78adcd679..b044b324c5 100644
--- a/grub-core/net/http.c
+++ b/grub-core/net/http.c
@@ -16,6 +16,7 @@
  *  along with GRUB.  If not, see .
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -508,13 +509,20 @@ http_open (struct grub_file *file, const char *filename)
 {
   grub_err_t err;
   struct http_data *data;
+  const char *http_path;
 
   data = grub_zalloc (sizeof (*data));
   if (!data)
 return grub_errno;
   file->size = GRUB_FILE_SIZE_UNKNOWN;
 
-  data->filename = grub_strdup (filename);
+  /* If path is relative, prepend http_path */
+  http_path = grub_env_get ("http_path");
+  if (http_path && filename[0] != '/')
+data->filename = grub_xasprintf ("%s/%s", http_path, filename);
+  else
+data->filename = grub_strdup (filename);
+
   if (!data->filename)
 {
   grub_free (data);
-- 
2.39.0


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v4 18/19] normal/main: Discover the device to read the config from as a fallback

2023-01-09 Thread Robbie Harwood
From: Javier Martinez Canillas 

When core.img is generated locally, the grub2-probe tool figures out the
device and partition that needs to be read to parse the GRUB
configuration file.

But in some cases the core.img can't be generated on the host and
instead has to be done at package build time.  In particular, this will
be true when it needs to be signed with a key that's only available on
the package building infrastructure.

In that case, the prefix variable won't have a device and partition but
only a directory path.  So there's no way for GRUB to know from which
device has to read the configuration file.

To allow GRUB to continue working on that scenario, fallback to
iterating over all the available devices if reading the config failed
when using the prefix and fw_path variables.

Signed-off-by: Javier Martinez Canillas 
Co-authored-by: Robbie Harwood 
Signed-off-by: Robbie Harwood 
---
 grub-core/normal/main.c | 58 -
 1 file changed, 51 insertions(+), 7 deletions(-)

diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index 58d3dcee8d..4d727971ea 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -311,18 +311,13 @@ grub_enter_normal_mode (const char *config)
 }
 
 static grub_err_t
-grub_try_normal (const char *variable)
+grub_try_normal_prefix (const char *prefix)
 {
 char *config;
-const char *prefix;
 grub_err_t err = GRUB_ERR_FILE_NOT_FOUND;
 const char *net_search_cfg;
 int disable_net_search = 0;
 
-prefix = grub_env_get (variable);
-if (!prefix)
-  return GRUB_ERR_FILE_NOT_FOUND;
-
 net_search_cfg = grub_env_get ("feature_net_search_cfg");
 if (net_search_cfg && net_search_cfg[0] == 'n')
   disable_net_search = 1;
@@ -336,7 +331,7 @@ grub_try_normal (const char *variable)
config = grub_malloc (config_len);
 
if (! config)
- return GRUB_ERR_FILE_NOT_FOUND;
+ return err;
 
grub_snprintf (config, config_len, "%s/grub.cfg", prefix);
err = grub_net_search_config_file (config);
@@ -365,6 +360,53 @@ grub_try_normal (const char *variable)
 return err;
 }
 
+static int
+grub_try_normal_dev (const char *name, void *data)
+{
+  grub_err_t err;
+  const char *prefix = grub_xasprintf ("(%s)%s", name, (char *) data);
+
+  if (!prefix)
+return 0;
+
+  err = grub_try_normal_prefix (prefix);
+  if (err == GRUB_ERR_NONE)
+return 1;
+
+  return 0;
+}
+
+static grub_err_t
+grub_try_normal_discover (void)
+{
+  const char *prefix = grub_env_get ("prefix");
+  grub_err_t err = GRUB_ERR_FILE_NOT_FOUND;
+
+  if (!prefix)
+return err;
+
+  if (grub_device_iterate (grub_try_normal_dev, (void *) prefix))
+return GRUB_ERR_NONE;
+
+  return err;
+}
+
+static grub_err_t
+grub_try_normal (const char *variable)
+{
+  grub_err_t err = GRUB_ERR_FILE_NOT_FOUND;
+  const char *prefix;
+
+  if (!variable)
+return err;
+
+  prefix = grub_env_get (variable);
+  if (!prefix)
+return err;
+
+  return grub_try_normal_prefix (prefix);
+}
+
 /* Enter normal mode from rescue mode.  */
 static grub_err_t
 grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
@@ -379,6 +421,8 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ 
((unused)),
   err = grub_try_normal ("fw_path");
   if (err == GRUB_ERR_FILE_NOT_FOUND)
 err = grub_try_normal ("prefix");
+  if (err == GRUB_ERR_FILE_NOT_FOUND)
+err = grub_try_normal_discover ();
   if (err == GRUB_ERR_FILE_NOT_FOUND)
 grub_enter_normal_mode (0);
 }
-- 
2.39.0


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel