|
|
a85e8e |
From 083e05daa723dcb8ddca934341d523e80c63aba4 Mon Sep 17 00:00:00 2001
|
|
|
a85e8e |
From: Michael Chang <mchang@suse.com>
|
|
|
a85e8e |
Date: Sun, 10 Jul 2016 23:46:31 +0800
|
|
|
a85e8e |
Subject: [PATCH 255/260] efinet: Setting network from UEFI device path
|
|
|
a85e8e |
|
|
|
a85e8e |
The PXE Base Code protocol used to obtain cached PXE DHCPACK packet is no
|
|
|
a85e8e |
longer provided for HTTP Boot. Instead, we have to get the HTTP boot
|
|
|
a85e8e |
information from the device path nodes defined in following UEFI Specification
|
|
|
a85e8e |
sections.
|
|
|
a85e8e |
|
|
|
a85e8e |
9.3.5.12 IPv4 Device Path
|
|
|
a85e8e |
9.3.5.13 IPv6 Device Path
|
|
|
a85e8e |
9.3.5.23 Uniform Resource Identifiers (URI) Device Path
|
|
|
a85e8e |
|
|
|
a85e8e |
This patch basically does:
|
|
|
a85e8e |
|
|
|
a85e8e |
include/grub/efi/api.h:
|
|
|
a85e8e |
Add new structure of Uniform Resource Identifiers (URI) Device Path
|
|
|
a85e8e |
|
|
|
a85e8e |
grub-core/net/drivers/efi/efinet.c:
|
|
|
a85e8e |
Check if PXE Base Code is available, if not it will try to obtain the netboot
|
|
|
a85e8e |
information from the device path where the image booted from. The DHCPACK
|
|
|
a85e8e |
packet is recoverd from the information in device patch and feed into the same
|
|
|
a85e8e |
DHCP packet processing functions to ensure the network interface is setting up
|
|
|
a85e8e |
the same way it used to be.
|
|
|
a85e8e |
|
|
|
a85e8e |
Signed-off-by: Michael Chang <mchang@suse.com>
|
|
|
a85e8e |
Signed-off-by: Ken Lin <ken.lin@hpe.com>
|
|
|
a85e8e |
---
|
|
|
a85e8e |
grub-core/net/drivers/efi/efinet.c | 293 +++++++++++++++++++++++++++++++++++--
|
|
|
a85e8e |
include/grub/efi/api.h | 11 ++
|
|
|
a85e8e |
2 files changed, 292 insertions(+), 12 deletions(-)
|
|
|
a85e8e |
|
|
|
a85e8e |
diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
|
|
|
a85e8e |
index c00ac2e64..08e9d7aa3 100644
|
|
|
a85e8e |
--- a/grub-core/net/drivers/efi/efinet.c
|
|
|
a85e8e |
+++ b/grub-core/net/drivers/efi/efinet.c
|
|
|
a85e8e |
@@ -27,6 +27,7 @@
|
|
|
a85e8e |
#include <grub/i18n.h>
|
|
|
a85e8e |
#include <grub/lib/hexdump.h>
|
|
|
a85e8e |
#include <grub/types.h>
|
|
|
a85e8e |
+#include <grub/net/netbuff.h>
|
|
|
a85e8e |
|
|
|
a85e8e |
GRUB_MOD_LICENSE ("GPLv3+");
|
|
|
a85e8e |
|
|
|
a85e8e |
@@ -342,6 +343,244 @@ grub_efinet_findcards (void)
|
|
|
a85e8e |
grub_free (handles);
|
|
|
a85e8e |
}
|
|
|
a85e8e |
|
|
|
a85e8e |
+static struct grub_net_buff *
|
|
|
a85e8e |
+grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *use_ipv6)
|
|
|
a85e8e |
+{
|
|
|
a85e8e |
+ grub_efi_uint16_t uri_len;
|
|
|
a85e8e |
+ grub_efi_device_path_t *ldp, *ddp;
|
|
|
a85e8e |
+ grub_efi_uri_device_path_t *uri_dp;
|
|
|
a85e8e |
+ struct grub_net_buff *nb;
|
|
|
a85e8e |
+ grub_err_t err;
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ ddp = grub_efi_duplicate_device_path (dp);
|
|
|
a85e8e |
+ if (!ddp)
|
|
|
a85e8e |
+ return NULL;
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ ldp = grub_efi_find_last_device_path (ddp);
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
|
|
|
a85e8e |
+ || GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)
|
|
|
a85e8e |
+ {
|
|
|
a85e8e |
+ grub_free (ddp);
|
|
|
a85e8e |
+ grub_free (ldp);
|
|
|
a85e8e |
+ return NULL;
|
|
|
a85e8e |
+ }
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ uri_len = GRUB_EFI_DEVICE_PATH_LENGTH (ldp) > 4 ? GRUB_EFI_DEVICE_PATH_LENGTH (ldp) - 4 : 0;
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ if (!uri_len)
|
|
|
a85e8e |
+ {
|
|
|
a85e8e |
+ grub_free (ddp);
|
|
|
a85e8e |
+ grub_free (ldp);
|
|
|
a85e8e |
+ return NULL;
|
|
|
a85e8e |
+ }
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ uri_dp = (grub_efi_uri_device_path_t *) ldp;
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
|
|
|
a85e8e |
+ ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
|
|
|
a85e8e |
+ ldp->length = sizeof (*ldp);
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ ldp = grub_efi_find_last_device_path (ddp);
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
|
|
|
a85e8e |
+ || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
|
|
|
a85e8e |
+ && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE))
|
|
|
a85e8e |
+ {
|
|
|
a85e8e |
+ grub_free (ddp);
|
|
|
a85e8e |
+ grub_free (ldp);
|
|
|
a85e8e |
+ return NULL;
|
|
|
a85e8e |
+ }
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ nb = grub_netbuff_alloc (512);
|
|
|
a85e8e |
+ if (!nb)
|
|
|
a85e8e |
+ {
|
|
|
a85e8e |
+ grub_free (ddp);
|
|
|
a85e8e |
+ grub_free (ldp);
|
|
|
a85e8e |
+ return NULL;
|
|
|
a85e8e |
+ }
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE)
|
|
|
a85e8e |
+ {
|
|
|
a85e8e |
+ grub_efi_ipv4_device_path_t *ipv4 = (grub_efi_ipv4_device_path_t *) ldp;
|
|
|
a85e8e |
+ struct grub_net_bootp_packet *bp;
|
|
|
a85e8e |
+ grub_uint8_t *ptr;
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ bp = (struct grub_net_bootp_packet *) nb->tail;
|
|
|
a85e8e |
+ err = grub_netbuff_put (nb, sizeof (*bp) + 4);
|
|
|
a85e8e |
+ if (err)
|
|
|
a85e8e |
+ {
|
|
|
a85e8e |
+ grub_free (ddp);
|
|
|
a85e8e |
+ grub_free (ldp);
|
|
|
a85e8e |
+ grub_netbuff_free (nb);
|
|
|
a85e8e |
+ return NULL;
|
|
|
a85e8e |
+ }
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ if (sizeof(bp->boot_file) < uri_len)
|
|
|
a85e8e |
+ {
|
|
|
a85e8e |
+ grub_free (ddp);
|
|
|
a85e8e |
+ grub_free (ldp);
|
|
|
a85e8e |
+ grub_netbuff_free (nb);
|
|
|
a85e8e |
+ return NULL;
|
|
|
a85e8e |
+ }
|
|
|
a85e8e |
+ grub_memcpy (bp->boot_file, uri_dp->uri, uri_len);
|
|
|
a85e8e |
+ grub_memcpy (&bp->your_ip, ipv4->local_ip_address, sizeof (bp->your_ip));
|
|
|
a85e8e |
+ grub_memcpy (&bp->server_ip, ipv4->remote_ip_address, sizeof (bp->server_ip));
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ bp->vendor[0] = GRUB_NET_BOOTP_RFC1048_MAGIC_0;
|
|
|
a85e8e |
+ bp->vendor[1] = GRUB_NET_BOOTP_RFC1048_MAGIC_1;
|
|
|
a85e8e |
+ bp->vendor[2] = GRUB_NET_BOOTP_RFC1048_MAGIC_2;
|
|
|
a85e8e |
+ bp->vendor[3] = GRUB_NET_BOOTP_RFC1048_MAGIC_3;
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ ptr = nb->tail;
|
|
|
a85e8e |
+ err = grub_netbuff_put (nb, sizeof (ipv4->subnet_mask) + 2);
|
|
|
a85e8e |
+ if (err)
|
|
|
a85e8e |
+ {
|
|
|
a85e8e |
+ grub_free (ddp);
|
|
|
a85e8e |
+ grub_free (ldp);
|
|
|
a85e8e |
+ grub_netbuff_free (nb);
|
|
|
a85e8e |
+ return NULL;
|
|
|
a85e8e |
+ }
|
|
|
a85e8e |
+ *ptr++ = GRUB_NET_BOOTP_NETMASK;
|
|
|
a85e8e |
+ *ptr++ = sizeof (ipv4->subnet_mask);
|
|
|
a85e8e |
+ grub_memcpy (ptr, ipv4->subnet_mask, sizeof (ipv4->subnet_mask));
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ ptr = nb->tail;
|
|
|
a85e8e |
+ err = grub_netbuff_put (nb, sizeof (ipv4->gateway_ip_address) + 2);
|
|
|
a85e8e |
+ if (err)
|
|
|
a85e8e |
+ {
|
|
|
a85e8e |
+ grub_free (ddp);
|
|
|
a85e8e |
+ grub_free (ldp);
|
|
|
a85e8e |
+ grub_netbuff_free (nb);
|
|
|
a85e8e |
+ return NULL;
|
|
|
a85e8e |
+ }
|
|
|
a85e8e |
+ *ptr++ = GRUB_NET_BOOTP_ROUTER;
|
|
|
a85e8e |
+ *ptr++ = sizeof (ipv4->gateway_ip_address);
|
|
|
a85e8e |
+ grub_memcpy (ptr, ipv4->gateway_ip_address, sizeof (ipv4->gateway_ip_address));
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ ptr = nb->tail;
|
|
|
a85e8e |
+ err = grub_netbuff_put (nb, sizeof ("HTTPClient") + 1);
|
|
|
a85e8e |
+ if (err)
|
|
|
a85e8e |
+ {
|
|
|
a85e8e |
+ grub_free (ddp);
|
|
|
a85e8e |
+ grub_free (ldp);
|
|
|
a85e8e |
+ grub_netbuff_free (nb);
|
|
|
a85e8e |
+ return NULL;
|
|
|
a85e8e |
+ }
|
|
|
a85e8e |
+ *ptr++ = GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER;
|
|
|
a85e8e |
+ *ptr++ = sizeof ("HTTPClient") - 1;
|
|
|
a85e8e |
+ grub_memcpy (ptr, "HTTPClient", sizeof ("HTTPClient") - 1);
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ ptr = nb->tail;
|
|
|
a85e8e |
+ err = grub_netbuff_put (nb, 1);
|
|
|
a85e8e |
+ if (err)
|
|
|
a85e8e |
+ {
|
|
|
a85e8e |
+ grub_free (ddp);
|
|
|
a85e8e |
+ grub_free (ldp);
|
|
|
a85e8e |
+ grub_netbuff_free (nb);
|
|
|
a85e8e |
+ return NULL;
|
|
|
a85e8e |
+ }
|
|
|
a85e8e |
+ *ptr = GRUB_NET_BOOTP_END;
|
|
|
a85e8e |
+ *use_ipv6 = 0;
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
|
|
|
a85e8e |
+ ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
|
|
|
a85e8e |
+ ldp->length = sizeof (*ldp);
|
|
|
a85e8e |
+ ldp = grub_efi_find_last_device_path (ddp);
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE)
|
|
|
a85e8e |
+ {
|
|
|
a85e8e |
+ grub_efi_mac_address_device_path_t *mac = (grub_efi_mac_address_device_path_t *) ldp;
|
|
|
a85e8e |
+ bp->hw_type = mac->if_type;
|
|
|
a85e8e |
+ bp->hw_len = sizeof (bp->mac_addr);
|
|
|
a85e8e |
+ grub_memcpy (bp->mac_addr, mac->mac_address, bp->hw_len);
|
|
|
a85e8e |
+ }
|
|
|
a85e8e |
+ }
|
|
|
a85e8e |
+ else
|
|
|
a85e8e |
+ {
|
|
|
a85e8e |
+ grub_efi_ipv6_device_path_t *ipv6 = (grub_efi_ipv6_device_path_t *) ldp;
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ struct grub_net_dhcp6_packet *d6p;
|
|
|
a85e8e |
+ struct grub_net_dhcp6_option *opt;
|
|
|
a85e8e |
+ struct grub_net_dhcp6_option_iana *iana;
|
|
|
a85e8e |
+ struct grub_net_dhcp6_option_iaaddr *iaaddr;
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ d6p = (struct grub_net_dhcp6_packet *)nb->tail;
|
|
|
a85e8e |
+ err = grub_netbuff_put (nb, sizeof(*d6p));
|
|
|
a85e8e |
+ if (err)
|
|
|
a85e8e |
+ {
|
|
|
a85e8e |
+ grub_free (ddp);
|
|
|
a85e8e |
+ grub_free (ldp);
|
|
|
a85e8e |
+ grub_netbuff_free (nb);
|
|
|
a85e8e |
+ return NULL;
|
|
|
a85e8e |
+ }
|
|
|
a85e8e |
+ d6p->message_type = GRUB_NET_DHCP6_REPLY;
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ opt = (struct grub_net_dhcp6_option *)nb->tail;
|
|
|
a85e8e |
+ err = grub_netbuff_put (nb, sizeof(*opt));
|
|
|
a85e8e |
+ if (err)
|
|
|
a85e8e |
+ {
|
|
|
a85e8e |
+ grub_free (ddp);
|
|
|
a85e8e |
+ grub_free (ldp);
|
|
|
a85e8e |
+ grub_netbuff_free (nb);
|
|
|
a85e8e |
+ return NULL;
|
|
|
a85e8e |
+ }
|
|
|
a85e8e |
+ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IA_NA);
|
|
|
a85e8e |
+ opt->len = grub_cpu_to_be16_compile_time (sizeof(*iana) + sizeof(*opt) + sizeof(*iaaddr));
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ err = grub_netbuff_put (nb, sizeof(*iana));
|
|
|
a85e8e |
+ if (err)
|
|
|
a85e8e |
+ {
|
|
|
a85e8e |
+ grub_free (ddp);
|
|
|
a85e8e |
+ grub_free (ldp);
|
|
|
a85e8e |
+ grub_netbuff_free (nb);
|
|
|
a85e8e |
+ return NULL;
|
|
|
a85e8e |
+ }
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ opt = (struct grub_net_dhcp6_option *)nb->tail;
|
|
|
a85e8e |
+ err = grub_netbuff_put (nb, sizeof(*opt));
|
|
|
a85e8e |
+ if (err)
|
|
|
a85e8e |
+ {
|
|
|
a85e8e |
+ grub_free (ddp);
|
|
|
a85e8e |
+ grub_free (ldp);
|
|
|
a85e8e |
+ grub_netbuff_free (nb);
|
|
|
a85e8e |
+ return NULL;
|
|
|
a85e8e |
+ }
|
|
|
a85e8e |
+ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IAADDR);
|
|
|
a85e8e |
+ opt->len = grub_cpu_to_be16_compile_time (sizeof (*iaaddr));
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ iaaddr = (struct grub_net_dhcp6_option_iaaddr *)nb->tail;
|
|
|
a85e8e |
+ err = grub_netbuff_put (nb, sizeof(*iaaddr));
|
|
|
a85e8e |
+ if (err)
|
|
|
a85e8e |
+ {
|
|
|
a85e8e |
+ grub_free (ddp);
|
|
|
a85e8e |
+ grub_free (ldp);
|
|
|
a85e8e |
+ grub_netbuff_free (nb);
|
|
|
a85e8e |
+ return NULL;
|
|
|
a85e8e |
+ }
|
|
|
a85e8e |
+ grub_memcpy (iaaddr->addr, ipv6->local_ip_address, sizeof(ipv6->local_ip_address));
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ opt = (struct grub_net_dhcp6_option *)nb->tail;
|
|
|
a85e8e |
+ err = grub_netbuff_put (nb, sizeof(*opt) + uri_len);
|
|
|
a85e8e |
+ if (err)
|
|
|
a85e8e |
+ {
|
|
|
a85e8e |
+ grub_free (ddp);
|
|
|
a85e8e |
+ grub_free (ldp);
|
|
|
a85e8e |
+ grub_netbuff_free (nb);
|
|
|
a85e8e |
+ return NULL;
|
|
|
a85e8e |
+ }
|
|
|
a85e8e |
+ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_BOOTFILE_URL);
|
|
|
a85e8e |
+ opt->len = grub_cpu_to_be16 (uri_len);
|
|
|
a85e8e |
+ grub_memcpy (opt->data, uri_dp->uri, uri_len);
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ *use_ipv6 = 1;
|
|
|
a85e8e |
+ }
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ grub_free (ldp);
|
|
|
a85e8e |
+ grub_free (ddp);
|
|
|
a85e8e |
+ return nb;
|
|
|
a85e8e |
+}
|
|
|
a85e8e |
+
|
|
|
a85e8e |
static void
|
|
|
a85e8e |
grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
|
|
|
a85e8e |
char **path)
|
|
|
a85e8e |
@@ -358,6 +597,10 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
|
|
|
a85e8e |
grub_efi_device_path_t *cdp;
|
|
|
a85e8e |
struct grub_efi_pxe *pxe;
|
|
|
a85e8e |
struct grub_efi_pxe_mode *pxe_mode;
|
|
|
a85e8e |
+ grub_uint8_t *packet_buf;
|
|
|
a85e8e |
+ grub_size_t packet_bufsz ;
|
|
|
a85e8e |
+ int ipv6;
|
|
|
a85e8e |
+ struct grub_net_buff *nb = NULL;
|
|
|
a85e8e |
|
|
|
a85e8e |
if (card->driver != &efidriver)
|
|
|
a85e8e |
continue;
|
|
|
a85e8e |
@@ -381,11 +624,21 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
|
|
|
a85e8e |
*/
|
|
|
a85e8e |
if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
|
|
|
a85e8e |
|| (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
|
|
|
a85e8e |
- && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE))
|
|
|
a85e8e |
+ && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE
|
|
|
a85e8e |
+ && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_URI_DEVICE_PATH_SUBTYPE))
|
|
|
a85e8e |
continue;
|
|
|
a85e8e |
dup_dp = grub_efi_duplicate_device_path (dp);
|
|
|
a85e8e |
if (!dup_dp)
|
|
|
a85e8e |
continue;
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)
|
|
|
a85e8e |
+ {
|
|
|
a85e8e |
+ dup_ldp = grub_efi_find_last_device_path (dup_dp);
|
|
|
a85e8e |
+ dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
|
|
|
a85e8e |
+ dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
|
|
|
a85e8e |
+ dup_ldp->length = sizeof (*dup_ldp);
|
|
|
a85e8e |
+ }
|
|
|
a85e8e |
+
|
|
|
a85e8e |
dup_ldp = grub_efi_find_last_device_path (dup_dp);
|
|
|
a85e8e |
dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
|
|
|
a85e8e |
dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
|
|
|
a85e8e |
@@ -398,20 +651,32 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
|
|
|
a85e8e |
|
|
|
a85e8e |
pxe = grub_efi_open_protocol (hnd, &pxe_io_guid,
|
|
|
a85e8e |
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
|
|
a85e8e |
- if (! pxe)
|
|
|
a85e8e |
- continue;
|
|
|
a85e8e |
+ if (!pxe)
|
|
|
a85e8e |
+ {
|
|
|
a85e8e |
+ nb = grub_efinet_create_dhcp_ack_from_device_path (dp, &ipv6);
|
|
|
a85e8e |
+ if (!nb)
|
|
|
a85e8e |
+ {
|
|
|
a85e8e |
+ grub_print_error ();
|
|
|
a85e8e |
+ continue;
|
|
|
a85e8e |
+ }
|
|
|
a85e8e |
+ packet_buf = nb->head;
|
|
|
a85e8e |
+ packet_bufsz = nb->tail - nb->head;
|
|
|
a85e8e |
+ }
|
|
|
a85e8e |
+ else
|
|
|
a85e8e |
+ {
|
|
|
a85e8e |
+ pxe_mode = pxe->mode;
|
|
|
a85e8e |
+ packet_buf = (grub_uint8_t *) &pxe_mode->dhcp_ack;
|
|
|
a85e8e |
+ packet_bufsz = sizeof (pxe_mode->dhcp_ack);
|
|
|
a85e8e |
+ ipv6 = pxe_mode->using_ipv6;
|
|
|
a85e8e |
+ }
|
|
|
a85e8e |
|
|
|
a85e8e |
- pxe_mode = pxe->mode;
|
|
|
a85e8e |
- if (pxe_mode->using_ipv6)
|
|
|
a85e8e |
+ if (ipv6)
|
|
|
a85e8e |
{
|
|
|
a85e8e |
grub_dprintf ("efinet", "using ipv6 and dhcpv6\n");
|
|
|
a85e8e |
- grub_dprintf ("efinet", "dhcp_ack_received: %s%s\n",
|
|
|
a85e8e |
- pxe_mode->dhcp_ack_received ? "yes" : "no",
|
|
|
a85e8e |
- pxe_mode->dhcp_ack_received ? "" : " cannot continue");
|
|
|
a85e8e |
grub_net_configure_by_dhcpv6_reply (card->name, card, 0,
|
|
|
a85e8e |
(struct grub_net_dhcp6_packet *)
|
|
|
a85e8e |
- &pxe_mode->dhcp_ack,
|
|
|
a85e8e |
- sizeof (pxe_mode->dhcp_ack),
|
|
|
a85e8e |
+ packet_buf,
|
|
|
a85e8e |
+ packet_bufsz,
|
|
|
a85e8e |
1, device, path);
|
|
|
a85e8e |
if (device && path)
|
|
|
a85e8e |
grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path);
|
|
|
a85e8e |
@@ -423,11 +688,15 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
|
|
|
a85e8e |
grub_dprintf ("efinet", "using ipv4 and dhcp\n");
|
|
|
a85e8e |
grub_net_configure_by_dhcp_ack (card->name, card, 0,
|
|
|
a85e8e |
(struct grub_net_bootp_packet *)
|
|
|
a85e8e |
- &pxe_mode->dhcp_ack,
|
|
|
a85e8e |
- sizeof (pxe_mode->dhcp_ack),
|
|
|
a85e8e |
+ packet_buf,
|
|
|
a85e8e |
+ packet_bufsz,
|
|
|
a85e8e |
1, device, path);
|
|
|
a85e8e |
grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path);
|
|
|
a85e8e |
}
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+ if (nb)
|
|
|
a85e8e |
+ grub_netbuff_free (nb);
|
|
|
a85e8e |
+
|
|
|
a85e8e |
return;
|
|
|
a85e8e |
}
|
|
|
a85e8e |
}
|
|
|
a85e8e |
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
|
|
|
a85e8e |
index 0821e3364..a37fb50de 100644
|
|
|
a85e8e |
--- a/include/grub/efi/api.h
|
|
|
a85e8e |
+++ b/include/grub/efi/api.h
|
|
|
a85e8e |
@@ -786,6 +786,8 @@ struct grub_efi_ipv4_device_path
|
|
|
a85e8e |
grub_efi_uint16_t remote_port;
|
|
|
a85e8e |
grub_efi_uint16_t protocol;
|
|
|
a85e8e |
grub_efi_uint8_t static_ip_address;
|
|
|
a85e8e |
+ grub_efi_ipv4_address_t gateway_ip_address;
|
|
|
a85e8e |
+ grub_efi_ipv4_address_t subnet_mask;
|
|
|
a85e8e |
} GRUB_PACKED;
|
|
|
a85e8e |
typedef struct grub_efi_ipv4_device_path grub_efi_ipv4_device_path_t;
|
|
|
a85e8e |
|
|
|
a85e8e |
@@ -840,6 +842,15 @@ struct grub_efi_sata_device_path
|
|
|
a85e8e |
} GRUB_PACKED;
|
|
|
a85e8e |
typedef struct grub_efi_sata_device_path grub_efi_sata_device_path_t;
|
|
|
a85e8e |
|
|
|
a85e8e |
+#define GRUB_EFI_URI_DEVICE_PATH_SUBTYPE 24
|
|
|
a85e8e |
+
|
|
|
a85e8e |
+struct grub_efi_uri_device_path
|
|
|
a85e8e |
+{
|
|
|
a85e8e |
+ grub_efi_device_path_t header;
|
|
|
a85e8e |
+ grub_efi_uint8_t uri[0];
|
|
|
a85e8e |
+} GRUB_PACKED;
|
|
|
a85e8e |
+typedef struct grub_efi_uri_device_path grub_efi_uri_device_path_t;
|
|
|
a85e8e |
+
|
|
|
a85e8e |
#define GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE 10
|
|
|
a85e8e |
|
|
|
a85e8e |
/* Media Device Path. */
|
|
|
a85e8e |
--
|
|
|
a85e8e |
2.13.0
|
|
|
a85e8e |
|