File grub2-efinet-httpboot.patch of Package grub2.16098
Index: grub-2.02~beta2/grub-core/net/bootp.c
===================================================================
--- grub-2.02~beta2.orig/grub-core/net/bootp.c
+++ grub-2.02~beta2/grub-core/net/bootp.c
@@ -121,6 +121,11 @@ parse_dhcp_vendor (const char *name, con
taglength);
break;
+ case GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER:
+ grub_env_set_net_property (name, "vendor_class_identifier", (const char *) ptr,
+ taglength);
+ break;
+
/* If you need any other options please contact GRUB
development team. */
}
@@ -180,9 +185,83 @@ grub_net_configure_by_dhcp_ack (const ch
grub_net_add_route (name, target, inter);
}
+ 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);
+
if (size > OFFSET_OF (boot_file, bp))
- grub_env_set_net_property (name, "boot_file", bp->boot_file,
+ {
+ char *cidvar;
+ const char *cid;
+ 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 *p, *q, *proto, *ip, *pa;
+ grub_size_t len;
+ p = grub_strstr (bp->boot_file, "://");
+ q = NULL;
+ if (p)
+ q = grub_strchr (p + grub_strlen("://"), '/');
+
+ if (p && q)
+ {
+ len = p - bp->boot_file;
+ proto = grub_malloc (len + 1);
+ grub_memcpy (proto, bp->boot_file, len);
+ proto[len] = '\0';
+ len = q - (p + 3);
+ ip = grub_malloc (len + 1);
+ grub_memcpy (ip, p + 3, len);
+ ip[len] = '\0';
+ pa = grub_strdup (q);
+ 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;
+ }
+ }
+ 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;
+ }
+ }
+ else
+ grub_env_set_net_property (name, "boot_file", bp->boot_file,
sizeof (bp->boot_file));
+ }
if (is_def)
grub_net_default_server = 0;
if (is_def && !grub_net_default_server && bp->server_ip)
@@ -241,9 +320,6 @@ grub_net_configure_by_dhcp_ack (const ch
**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);
if (inter->dhcp_ack)
@@ -257,54 +333,6 @@ grub_net_configure_by_dhcp_ack (const ch
return inter;
}
-struct grub_dhcpv6_option {
- grub_uint16_t code;
- grub_uint16_t len;
- grub_uint8_t data[0];
-} GRUB_PACKED;
-
-
-struct grub_dhcpv6_iana_option {
- grub_uint32_t iaid;
- grub_uint32_t t1;
- grub_uint32_t t2;
- grub_uint8_t data[0];
-} GRUB_PACKED;
-
-struct grub_dhcpv6_iaaddr_option {
- grub_uint8_t addr[16];
- grub_uint32_t preferred_lifetime;
- grub_uint32_t valid_lifetime;
- grub_uint8_t data[0];
-} GRUB_PACKED;
-
-struct grub_DUID_LL
-{
- grub_uint16_t type;
- grub_uint16_t hw_type;
- grub_uint8_t hwaddr[6];
-} GRUB_PACKED;
-
-struct grub_dhcpv6_dns_servers {
- grub_uint8_t addr[16];
- grub_uint8_t next_addr[0];
-} GRUB_PACKED;
-
-//http://tools.ietf.org/html/rfc1035#section-3.1
-
-#define DHCPv6_REPLY 7
-#define DHCPv6_ADVERTISE 2
-#define DHCPv6_REQUEST 3
-#define OPTION_BOOTFILE_URL 59
-//RFC3646 http://tools.ietf.org/html/rfc3646
-#define OPTION_DNS_SERVERS 23
-#define OPTION_IA_NA 3
-#define OPTION_IAADDR 5
-#define OPTION_CLIENTID 1
-#define OPTION_SERVERID 2
-#define OPTION_ORO 6
-#define OPTION_ELAPSED_TIME 8
-
struct grub_dhcpv6_session
{
struct grub_dhcpv6_session *next;
@@ -554,19 +582,15 @@ find_bootfile_url (const struct grub_net
ip_start = ip_end = NULL;
ip_start = bootfile_url + grub_strlen(pr);
+ path = grub_strchr (ip_start, '/');
- if (*ip_start != '[')
- ip_start = NULL;
- else
- ip_end = grub_strchr (++ip_start, ']');
-
- if (!ip_start || !ip_end)
+ if (!ip_start || !path)
{
- grub_error (GRUB_ERR_IO, N_("IPv6-address not in square brackets"));
+ grub_error (GRUB_ERR_IO, N_("invalid url format"));
goto cleanup;
}
- ip_len = ip_end - ip_start;
+ ip_len = path - ip_start;
if (proto)
{
@@ -582,6 +606,13 @@ find_bootfile_url (const struct grub_net
if (server_ip)
{
+
+ if (ip_len > 2 && *ip_start == '[' && *(ip_start + ip_len - 1) == ']')
+ {
+ ++ip_start;
+ ip_len -= 2;
+ }
+
*server_ip = grub_malloc (ip_len + 1);
if (!*server_ip)
@@ -591,8 +622,6 @@ find_bootfile_url (const struct grub_net
*(*server_ip + ip_len) = '\0';
}
- path = ip_end + 1;
-
if (boot_file)
{
*boot_file = grub_strdup (path);
@@ -747,8 +776,8 @@ grub_net_configure_by_dhcpv6_adv (const
popt = (struct grub_dhcpv6_option*) nb->data;
popt->code = grub_cpu_to_be16 (OPTION_ORO);
popt->len = grub_cpu_to_be16 (4);
- *((grub_uint16_t *) popt->data) = grub_cpu_to_be16 (OPTION_BOOTFILE_URL);
- *((grub_uint16_t *) (popt->data + 2)) = grub_cpu_to_be16 (OPTION_DNS_SERVERS);
+ grub_set_unaligned16 (popt->data, grub_cpu_to_be16 (OPTION_BOOTFILE_URL));
+ grub_set_unaligned16 (popt->data + 2, grub_cpu_to_be16 (OPTION_DNS_SERVERS));
err = grub_netbuff_push (nb, 6);
if (err)
@@ -766,7 +795,7 @@ grub_net_configure_by_dhcpv6_adv (const
if (elapsed > 0xffff)
elapsed = 0xffff;
- *((grub_uint16_t *) popt->data) = grub_cpu_to_be16 ((grub_uint16_t)elapsed);
+ grub_set_unaligned16 (popt->data, grub_cpu_to_be16 ((grub_uint16_t)elapsed));
err = grub_netbuff_push (nb, 4);
if (err)
@@ -1381,7 +1410,7 @@ grub_cmd_bootp6 (struct grub_command *cm
opt = (struct grub_dhcpv6_option *)nb->data;
opt->code = grub_cpu_to_be16 (OPTION_ELAPSED_TIME);
opt->len = grub_cpu_to_be16 (2);
- *((grub_uint16_t *) opt->data) = 0;
+ grub_set_unaligned16 (opt->data, 0);
err = grub_netbuff_push (nb, sizeof(*duid) + 4);
if (err)
Index: grub-2.02~beta2/grub-core/net/drivers/efi/efinet.c
===================================================================
--- grub-2.02~beta2.orig/grub-core/net/drivers/efi/efinet.c
+++ grub-2.02~beta2/grub-core/net/drivers/efi/efinet.c
@@ -23,12 +23,15 @@
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
#include <grub/i18n.h>
+#include <grub/net/netbuff.h>
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,
@@ -364,6 +367,380 @@ 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)
+{
+ 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;
+ 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);
+ 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);
+
+ 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);
+ }
+
+ ptr = nb->tail;
+ err = grub_netbuff_put (nb, 1);
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ *ptr = 0xff;
+ *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_dhcpv6_packet *d6p;
+ struct grub_dhcpv6_option *opt;
+ struct grub_dhcpv6_iana_option *iana;
+ struct grub_dhcpv6_iaaddr_option *iaaddr;
+ grub_efi_ipv6_address_t *dns;
+ grub_efi_uintn_t num_dns;
+
+ d6p = (struct grub_net_dhcpv6_packet *)nb->tail;
+ err = grub_netbuff_put (nb, sizeof(*d6p));
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ d6p->message_type = DHCPv6_REPLY;
+
+ opt = (struct grub_dhcpv6_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 (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_dhcpv6_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 (OPTION_IAADDR);
+ opt->len = grub_cpu_to_be16_compile_time (sizeof (*iaaddr));
+
+ iaaddr = (struct grub_dhcpv6_iaaddr_option *)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_dhcpv6_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 (OPTION_BOOTFILE_URL);
+ 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_dhcpv6_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 (OPTION_DNS_SERVERS);
+ opt->len = grub_cpu_to_be16_compile_time (size_dns);
+ grub_memcpy (opt->data, dns, size_dns);
+ }
+
+ *use_ipv6 = 1;
+ }
+
+ return nb;
+}
+
+
static void
grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
char **path)
@@ -380,6 +757,11 @@ grub_efi_net_config_real (grub_efi_handl
grub_efi_device_path_t *cdp;
struct grub_efi_pxe *pxe;
struct grub_efi_pxe_mode *pxe_mode;
+ grub_uint8_t *dhcp_ack;
+ grub_size_t dhcp_ack_size ;
+ int ipv6;
+ struct grub_net_buff *nb = NULL;
+
if (card->driver != &efidriver)
continue;
cdp = grub_efi_get_device_path (card->efi_handle);
@@ -399,11 +781,21 @@ grub_efi_net_config_real (grub_efi_handl
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;
@@ -415,29 +807,44 @@ grub_efi_net_config_real (grub_efi_handl
}
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)
+ continue;
+ dhcp_ack = nb->head;
+ dhcp_ack_size = nb->tail - nb->head;
+ }
+ else
+ {
+ pxe_mode = pxe->mode;
+ dhcp_ack = (grub_uint8_t *) &pxe_mode->dhcp_ack;
+ dhcp_ack_size = 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_dhcpv6_packet *)
- &pxe_mode->dhcp_ack,
- sizeof (pxe_mode->dhcp_ack),
+ dhcp_ack,
+ dhcp_ack_size,
1, device, path);
if (grub_errno)
grub_print_error ();
- return;
}
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),
+ dhcp_ack,
+ dhcp_ack_size,
1, device, path);
}
+
+ if (nb)
+ grub_netbuff_free (nb);
+
return;
}
}
Index: grub-2.02~beta2/grub-core/net/http.c
===================================================================
--- grub-2.02~beta2.orig/grub-core/net/http.c
+++ grub-2.02~beta2/grub-core/net/http.c
@@ -312,24 +312,49 @@ http_establish (struct grub_file *file,
int i;
struct grub_net_buff *nb;
grub_err_t err;
+ grub_net_network_level_netaddress_t addr;
+ char *host;
+
+ grub_error_push ();
+ err = grub_net_resolve_net_address (file->device->net->server, &addr);
+ grub_error_pop ();
+
+ if (err == GRUB_ERR_NONE &&
+ addr.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6 &&
+ addr.ipv6.masksize == 128)
+ {
+ int hostsz = grub_strlen (file->device->net->server) + 3;
+ host = grub_malloc (hostsz);
+ if (host)
+ grub_snprintf (host, hostsz, "[%s]", file->device->net->server);
+ }
+ else
+ host = grub_strdup (file->device->net->server);
+
+ if (!host)
+ return grub_errno;
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 (host)
+ sizeof ("\r\nUser-Agent: " PACKAGE_STRING
"\r\n") - 1
+ sizeof ("Range: bytes=XXXXXXXXXXXXXXXXXXXX"
"-\r\n\r\n"));
if (!nb)
- return grub_errno;
+ {
+ grub_free (host);
+ return grub_errno;
+ }
grub_netbuff_reserve (nb, GRUB_NET_TCP_RESERVE_SIZE);
ptr = nb->tail;
err = grub_netbuff_put (nb, sizeof ("GET ") - 1);
if (err)
{
+ grub_free (host);
grub_netbuff_free (nb);
return err;
}
@@ -340,6 +365,7 @@ http_establish (struct grub_file *file,
err = grub_netbuff_put (nb, grub_strlen (data->filename));
if (err)
{
+ grub_free (host);
grub_netbuff_free (nb);
return err;
}
@@ -349,6 +375,7 @@ http_establish (struct grub_file *file,
err = grub_netbuff_put (nb, sizeof (" HTTP/1.1\r\nHost: ") - 1);
if (err)
{
+ grub_free (host);
grub_netbuff_free (nb);
return err;
}
@@ -356,14 +383,15 @@ http_establish (struct grub_file *file,
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 (host));
if (err)
{
+ grub_free (host);
grub_netbuff_free (nb);
return err;
}
- grub_memcpy (ptr, file->device->net->server,
- grub_strlen (file->device->net->server));
+ grub_memcpy (ptr, host, grub_strlen (host));
+ grub_free (host);
ptr = nb->tail;
err = grub_netbuff_put (nb,
@@ -381,9 +409,8 @@ http_establish (struct grub_file *file,
ptr = nb->tail;
grub_snprintf ((char *) ptr,
sizeof ("Range: bytes=XXXXXXXXXXXXXXXXXXXX-"
- "\r\n"
"\r\n"),
- "Range: bytes=%" PRIuGRUB_UINT64_T "-\r\n\r\n",
+ "Range: bytes=%" PRIuGRUB_UINT64_T "-\r\n",
offset);
grub_netbuff_put (nb, grub_strlen ((char *) ptr));
}
Index: grub-2.02~beta2/include/grub/efi/api.h
===================================================================
--- grub-2.02~beta2.orig/include/grub/efi/api.h
+++ grub-2.02~beta2/include/grub/efi/api.h
@@ -286,6 +286,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;
@@ -776,6 +786,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;
@@ -830,6 +842,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. */
@@ -1627,6 +1648,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__)
Index: grub-2.02~beta2/include/grub/net.h
===================================================================
--- grub-2.02~beta2.orig/include/grub/net.h
+++ grub-2.02~beta2/include/grub/net.h
@@ -433,6 +433,53 @@ struct grub_net_dhcpv6_packet
grub_uint8_t dhcp_options[0];
} GRUB_PACKED;
+struct grub_dhcpv6_option {
+ grub_uint16_t code;
+ grub_uint16_t len;
+ grub_uint8_t data[0];
+} GRUB_PACKED;
+
+struct grub_dhcpv6_iana_option {
+ grub_uint32_t iaid;
+ grub_uint32_t t1;
+ grub_uint32_t t2;
+ grub_uint8_t data[0];
+} GRUB_PACKED;
+
+struct grub_dhcpv6_iaaddr_option {
+ grub_uint8_t addr[16];
+ grub_uint32_t preferred_lifetime;
+ grub_uint32_t valid_lifetime;
+ grub_uint8_t data[0];
+} GRUB_PACKED;
+
+struct grub_DUID_LL
+{
+ grub_uint16_t type;
+ grub_uint16_t hw_type;
+ grub_uint8_t hwaddr[6];
+} GRUB_PACKED;
+
+struct grub_dhcpv6_dns_servers {
+ grub_uint8_t addr[16];
+ grub_uint8_t next_addr[0];
+} GRUB_PACKED;
+
+//http://tools.ietf.org/html/rfc1035#section-3.1
+
+#define DHCPv6_REPLY 7
+#define DHCPv6_ADVERTISE 2
+#define DHCPv6_REQUEST 3
+#define OPTION_BOOTFILE_URL 59
+//RFC3646 http://tools.ietf.org/html/rfc3646
+#define OPTION_DNS_SERVERS 23
+#define OPTION_IA_NA 3
+#define OPTION_IAADDR 5
+#define OPTION_CLIENTID 1
+#define OPTION_SERVERID 2
+#define OPTION_ORO 6
+#define OPTION_ELAPSED_TIME 8
+
#define GRUB_NET_BOOTP_RFC1048_MAGIC_0 0x63
#define GRUB_NET_BOOTP_RFC1048_MAGIC_1 0x82
#define GRUB_NET_BOOTP_RFC1048_MAGIC_2 0x53
@@ -448,6 +495,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
};