summaryrefslogtreecommitdiffstats
path: root/debian/patches/efinet-set-dns-from-uefi-proto.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/efinet-set-dns-from-uefi-proto.patch')
-rw-r--r--debian/patches/efinet-set-dns-from-uefi-proto.patch341
1 files changed, 341 insertions, 0 deletions
diff --git a/debian/patches/efinet-set-dns-from-uefi-proto.patch b/debian/patches/efinet-set-dns-from-uefi-proto.patch
new file mode 100644
index 0000000..9b5861b
--- /dev/null
+++ b/debian/patches/efinet-set-dns-from-uefi-proto.patch
@@ -0,0 +1,341 @@
+From 5a2c53dd059351cf385575fa99d5763bc07e0de2 Mon Sep 17 00:00:00 2001
+From: Michael Chang <mchang@suse.com>
+Date: Thu, 27 Oct 2016 17:43:21 -0400
+Subject: efinet: Setting DNS server from UEFI protocol
+
+In the URI device path node, any name rahter than address can be used for
+looking up the resources so that DNS service become needed to get answer of the
+name's address. Unfortunately the DNS is not defined in any of the device path
+nodes so that we use the EFI_IP4_CONFIG2_PROTOCOL and EFI_IP6_CONFIG_PROTOCOL
+to obtain it.
+
+These two protcols are defined the sections of UEFI specification.
+
+ 27.5 EFI IPv4 Configuration II Protocol
+ 27.7 EFI IPv6 Configuration Protocol
+
+include/grub/efi/api.h:
+Add new structure and protocol UUID of EFI_IP4_CONFIG2_PROTOCOL and
+EFI_IP6_CONFIG_PROTOCOL.
+
+grub-core/net/drivers/efi/efinet.c:
+Use the EFI_IP4_CONFIG2_PROTOCOL and EFI_IP6_CONFIG_PROTOCOL to obtain the list
+of DNS server address for IPv4 and IPv6 respectively. The address of DNS
+servers is structured into DHCPACK packet and feed into the same DHCP packet
+processing functions to ensure the network interface is setting up the same way
+it used to be.
+
+Signed-off-by: Michael Chang <mchang@suse.com>
+Signed-off-by: Ken Lin <ken.lin@hpe.com>
+
+Last-Update: 2021-09-24
+
+Patch-Name: efinet-set-dns-from-uefi-proto.patch
+---
+ grub-core/net/drivers/efi/efinet.c | 163 +++++++++++++++++++++++++++++
+ include/grub/efi/api.h | 76 ++++++++++++++
+ 2 files changed, 239 insertions(+)
+
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index 2d3b00f0e..82a28fb6e 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -30,6 +30,8 @@ GRUB_MOD_LICENSE ("GPLv3+");
+ /* GUID. */
+ static grub_efi_guid_t net_io_guid = GRUB_EFI_SIMPLE_NETWORK_GUID;
+ static grub_efi_guid_t pxe_io_guid = GRUB_EFI_PXE_GUID;
++static grub_efi_guid_t ip4_config_guid = GRUB_EFI_IP4_CONFIG2_PROTOCOL_GUID;
++static grub_efi_guid_t ip6_config_guid = GRUB_EFI_IP6_CONFIG_PROTOCOL_GUID;
+
+ static grub_err_t
+ send_card_buffer (struct grub_net_card *dev,
+@@ -325,6 +327,125 @@ grub_efinet_findcards (void)
+ grub_free (handles);
+ }
+
++static grub_efi_handle_t
++grub_efi_locate_device_path (grub_efi_guid_t *protocol, grub_efi_device_path_t *device_path,
++ grub_efi_device_path_t **r_device_path)
++{
++ grub_efi_handle_t handle;
++ grub_efi_status_t status;
++
++ status = efi_call_3 (grub_efi_system_table->boot_services->locate_device_path,
++ protocol, &device_path, &handle);
++
++ if (status != GRUB_EFI_SUCCESS)
++ return 0;
++
++ if (r_device_path)
++ *r_device_path = device_path;
++
++ return handle;
++}
++
++static grub_efi_ipv4_address_t *
++grub_dns_server_ip4_address (grub_efi_device_path_t *dp, grub_efi_uintn_t *num_dns)
++{
++ grub_efi_handle_t hnd;
++ grub_efi_status_t status;
++ grub_efi_ip4_config2_protocol_t *conf;
++ grub_efi_ipv4_address_t *addrs;
++ grub_efi_uintn_t data_size = 1 * sizeof (grub_efi_ipv4_address_t);
++
++ hnd = grub_efi_locate_device_path (&ip4_config_guid, dp, NULL);
++
++ if (!hnd)
++ return 0;
++
++ conf = grub_efi_open_protocol (hnd, &ip4_config_guid,
++ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
++
++ if (!conf)
++ return 0;
++
++ addrs = grub_malloc (data_size);
++ if (!addrs)
++ return 0;
++
++ status = efi_call_4 (conf->get_data, conf,
++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER,
++ &data_size, addrs);
++
++ if (status == GRUB_EFI_BUFFER_TOO_SMALL)
++ {
++ grub_free (addrs);
++ addrs = grub_malloc (data_size);
++ if (!addrs)
++ return 0;
++
++ status = efi_call_4 (conf->get_data, conf,
++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER,
++ &data_size, addrs);
++ }
++
++ if (status != GRUB_EFI_SUCCESS)
++ {
++ grub_free (addrs);
++ return 0;
++ }
++
++ *num_dns = data_size / sizeof (grub_efi_ipv4_address_t);
++ return addrs;
++}
++
++static grub_efi_ipv6_address_t *
++grub_dns_server_ip6_address (grub_efi_device_path_t *dp, grub_efi_uintn_t *num_dns)
++{
++ grub_efi_handle_t hnd;
++ grub_efi_status_t status;
++ grub_efi_ip6_config_protocol_t *conf;
++ grub_efi_ipv6_address_t *addrs;
++ grub_efi_uintn_t data_size = 1 * sizeof (grub_efi_ipv6_address_t);
++
++ hnd = grub_efi_locate_device_path (&ip6_config_guid, dp, NULL);
++
++ if (!hnd)
++ return 0;
++
++ conf = grub_efi_open_protocol (hnd, &ip6_config_guid,
++ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
++
++ if (!conf)
++ return 0;
++
++ addrs = grub_malloc (data_size);
++ if (!addrs)
++ return 0;
++
++ status = efi_call_4 (conf->get_data, conf,
++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER,
++ &data_size, addrs);
++
++ if (status == GRUB_EFI_BUFFER_TOO_SMALL)
++ {
++ grub_free (addrs);
++ addrs = grub_malloc (data_size);
++ if (!addrs)
++ return 0;
++
++ status = efi_call_4 (conf->get_data, conf,
++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER,
++ &data_size, addrs);
++ }
++
++ if (status != GRUB_EFI_SUCCESS)
++ {
++ grub_free (addrs);
++ return 0;
++ }
++
++ *num_dns = data_size / sizeof (grub_efi_ipv6_address_t);
++ return addrs;
++}
++
+ static struct grub_net_buff *
+ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *use_ipv6)
+ {
+@@ -377,6 +498,8 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u
+ grub_efi_ipv4_device_path_t *ipv4 = (grub_efi_ipv4_device_path_t *) ldp;
+ struct grub_net_bootp_packet *bp;
+ grub_uint8_t *ptr;
++ grub_efi_ipv4_address_t *dns;
++ grub_efi_uintn_t num_dns;
+
+ bp = (struct grub_net_bootp_packet *) nb->tail;
+ err = grub_netbuff_put (nb, sizeof (*bp) + 4);
+@@ -438,6 +561,25 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u
+ *ptr++ = sizeof ("HTTPClient") - 1;
+ grub_memcpy (ptr, "HTTPClient", sizeof ("HTTPClient") - 1);
+
++ dns = grub_dns_server_ip4_address (dp, &num_dns);
++ if (dns)
++ {
++ grub_efi_uintn_t size_dns = sizeof (*dns) * num_dns;
++
++ ptr = nb->tail;
++ err = grub_netbuff_put (nb, size_dns + 2);
++ if (err)
++ {
++ grub_free (ddp);
++ grub_netbuff_free (nb);
++ return NULL;
++ }
++ *ptr++ = GRUB_NET_BOOTP_DNS;
++ *ptr++ = size_dns;
++ grub_memcpy (ptr, dns, size_dns);
++ grub_free (dns);
++ }
++
+ ptr = nb->tail;
+ err = grub_netbuff_put (nb, 1);
+ if (err)
+@@ -470,6 +612,8 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u
+ struct grub_net_dhcp6_option *opt;
+ struct grub_net_dhcp6_option_iana *iana;
+ struct grub_net_dhcp6_option_iaaddr *iaaddr;
++ grub_efi_ipv6_address_t *dns;
++ grub_efi_uintn_t num_dns;
+
+ d6p = (struct grub_net_dhcp6_packet *)nb->tail;
+ err = grub_netbuff_put (nb, sizeof(*d6p));
+@@ -533,6 +677,25 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u
+ opt->len = grub_cpu_to_be16 (uri_len);
+ grub_memcpy (opt->data, uri_dp->uri, uri_len);
+
++ dns = grub_dns_server_ip6_address (dp, &num_dns);
++ if (dns)
++ {
++ grub_efi_uintn_t size_dns = sizeof (*dns) * num_dns;
++
++ opt = (struct grub_net_dhcp6_option *)nb->tail;
++ err = grub_netbuff_put (nb, sizeof(*opt) + size_dns);
++ if (err)
++ {
++ grub_free (ddp);
++ grub_netbuff_free (nb);
++ return NULL;
++ }
++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_DNS_SERVERS);
++ opt->len = grub_cpu_to_be16 (size_dns);
++ grub_memcpy (opt->data, dns, size_dns);
++ grub_free (dns);
++ }
++
+ *use_ipv6 = 1;
+ }
+
+diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
+index 4b4652ca5..9cab1a51d 100644
+--- a/include/grub/efi/api.h
++++ b/include/grub/efi/api.h
+@@ -354,6 +354,16 @@
+ { 0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44 } \
+ }
+
++#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;
+@@ -1793,6 +1803,72 @@ struct grub_efi_rng_protocol
+ };
+ typedef struct grub_efi_rng_protocol grub_efi_rng_protocol_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__) \
+ || defined(__riscv)