Hello community, here is the log from the commit of package grub2 for openSUSE:Factory checked in at 2016-08-11 18:53:05 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/grub2 (Old) and /work/SRC/openSUSE:Factory/.grub2.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "grub2" Changes: -------- --- /work/SRC/openSUSE:Factory/grub2/grub2.changes 2016-07-01 09:54:00.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.grub2.new/grub2.changes 2016-08-11 18:53:07.000000000 +0200 @@ -1,0 +2,38 @@ +Wed Aug 3 04:45:51 UTC 2016 - mch...@suse.com + +- grub.default: Empty GRUB_CMDLINE_LINUX_DEFAULT, the value will be fully + taken from YaST settings. (bsc#989803) + +------------------------------------------------------------------- +Wed Aug 3 04:45:34 UTC 2016 - mch...@suse.com + +- Add patches from Roberto Sassu <rsa...@suse.de> +- Fix grub2-10_linux-avoid-multi-device-root-kernel-argument.patch, + device path is not tested if GRUB_DISABLE_LINUX_UUID="true" + - added grub2-fix-multi-device-root-kernel-argument.patch + (bsc#960776) +- grub2-zipl-setup: avoid multi-device root= kernel argument + * added grub2-zipl-setup-fix-btrfs-multipledev.patch + (bsc#960776) +- Add SUSE_REMOVE_LINUX_ROOT_PARAM configuration option + to /etc/default/grub, to remove root= and rootflags= from the + kernel command line in /boot/grub2/grub.cfg and /boot/zipl/config + - added grub2-suse-remove-linux-root-param.patch + (bsc#962585) + +------------------------------------------------------------------- +Tue Aug 2 09:05:11 UTC 2016 - mch...@suse.com + +- Support HTTP Boot IPv4 and IPv6 (fate#320129) + * 0001-misc-fix-invalid-character-recongition-in-strto-l.patch + * 0002-net-read-bracketed-ipv6-addrs-and-port-numbers.patch + * 0003-bootp-New-net_bootp6-command.patch + * 0004-efinet-UEFI-IPv6-PXE-support.patch + * 0005-grub.texi-Add-net_bootp6-doument.patch + * 0006-bootp-Add-processing-DHCPACK-packet-from-HTTP-Boot.patch + * 0007-efinet-Setting-network-from-UEFI-device-path.patch + * 0008-efinet-Setting-DNS-server-from-UEFI-protocol.patch +- Fix heap corruption after dns lookup + * 0001-dns-fix-buffer-overflow-for-data-addresses-in-recv_h.patch + +------------------------------------------------------------------- New: ---- 0001-dns-fix-buffer-overflow-for-data-addresses-in-recv_h.patch 0001-misc-fix-invalid-character-recongition-in-strto-l.patch 0002-net-read-bracketed-ipv6-addrs-and-port-numbers.patch 0003-bootp-New-net_bootp6-command.patch 0004-efinet-UEFI-IPv6-PXE-support.patch 0005-grub.texi-Add-net_bootp6-doument.patch 0006-bootp-Add-processing-DHCPACK-packet-from-HTTP-Boot.patch 0007-efinet-Setting-network-from-UEFI-device-path.patch 0008-efinet-Setting-DNS-server-from-UEFI-protocol.patch grub2-fix-multi-device-root-kernel-argument.patch grub2-suse-remove-linux-root-param.patch grub2-zipl-setup-fix-btrfs-multipledev.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ grub2.spec ++++++ --- /var/tmp/diff_new_pack.rsNj0l/_old 2016-08-11 18:53:09.000000000 +0200 +++ /var/tmp/diff_new_pack.rsNj0l/_new 2016-08-11 18:53:09.000000000 +0200 @@ -184,8 +184,7 @@ Patch70: grub2-default-distributor.patch Patch71: grub2-menu-unrestricted.patch Patch72: grub2-mkconfig-arm.patch -Patch73: 0001-10_linux-Fix-grouping-of-tests-for-GRUB_DEVICE.patch -Patch74: 0002-20_linux_xen-fix-test-for-GRUB_DEVICE.patch +Patch73: 0001-dns-fix-buffer-overflow-for-data-addresses-in-recv_h.patch # Btrfs snapshot booting related patches Patch101: grub2-btrfs-01-add-ability-to-boot-from-subvolumes.patch Patch102: grub2-btrfs-02-export-subvolume-envvars.patch @@ -206,6 +205,12 @@ Patch141: grub2-SUSE-Add-the-t-hotkey.patch # EFI free memory on exit fix (bsc#980739) Patch150: grub2-efi-Free-malloc-regions-on-exit.patch +# Linux root device related patches +Patch160: 0001-10_linux-Fix-grouping-of-tests-for-GRUB_DEVICE.patch +Patch161: 0002-20_linux_xen-fix-test-for-GRUB_DEVICE.patch +Patch162: grub2-fix-multi-device-root-kernel-argument.patch +Patch163: grub2-zipl-setup-fix-btrfs-multipledev.patch +Patch164: grub2-suse-remove-linux-root-param.patch # PPC64 LE support Patch205: grub2-ppc64le-disable-video.patch Patch207: grub2-ppc64le-memory-map.patch @@ -213,6 +218,15 @@ Patch235: 0002-Add-Virtual-LAN-support.patch Patch236: grub2-efi_gop-avoid-low-resolution.patch Patch277: grub2-ppc64-cas-reboot-support.patch +# Support HTTP Boot IPv4 and IPv6 (fate#320129) +Patch280: 0001-misc-fix-invalid-character-recongition-in-strto-l.patch +Patch281: 0002-net-read-bracketed-ipv6-addrs-and-port-numbers.patch +Patch282: 0003-bootp-New-net_bootp6-command.patch +Patch283: 0004-efinet-UEFI-IPv6-PXE-support.patch +Patch284: 0005-grub.texi-Add-net_bootp6-doument.patch +Patch285: 0006-bootp-Add-processing-DHCPACK-packet-from-HTTP-Boot.patch +Patch286: 0007-efinet-Setting-network-from-UEFI-device-path.patch +Patch287: 0008-efinet-Setting-DNS-server-from-UEFI-protocol.patch Requires: gettext-runtime %if 0%{?suse_version} >= 1140 @@ -372,12 +386,6 @@ %setup -q -n grub-%{version} -a 5 (cd po && ls *.po | cut -d. -f1 | xargs) >po/LINGUAS %patch1 -p1 -# This simplifies patch handling without need to use git to create patch -# that renames file -mv docs/grub.texi docs/grub2.texi -# This avoids attempt to rebuild potfiles which fails because necessary -# sources are not included in tarball -mv po/grub.pot po/%{name}.pot %patch2 -p1 %patch3 -p1 %patch6 -p1 @@ -415,7 +423,6 @@ %patch71 -p1 %patch72 -p1 %patch73 -p1 -%patch74 -p1 %patch101 -p1 %patch102 -p1 %patch103 -p1 @@ -431,12 +438,32 @@ %patch140 -p1 %patch141 -p1 %patch150 -p1 +%patch160 -p1 +%patch161 -p1 +%patch162 -p1 +%patch163 -p1 +%patch164 -p1 %patch205 -p1 %patch207 -p1 %patch233 -p1 %patch235 -p1 %patch236 -p1 %patch277 -p1 +%patch280 -p1 +%patch281 -p1 +%patch282 -p1 +%patch283 -p1 +%patch284 -p1 +%patch285 -p1 +%patch286 -p1 +%patch287 -p1 + +# This simplifies patch handling without need to use git to create patch +# that renames file +mv docs/grub.texi docs/grub2.texi +# This avoids attempt to rebuild potfiles which fails because necessary +# sources are not included in tarball +mv po/grub.pot po/%{name}.pot # Generate po/LINGUAS for message catalogs ... ./linguas.sh ++++++ 0001-dns-fix-buffer-overflow-for-data-addresses-in-recv_h.patch ++++++ >From 52408aa94604466bdd80f48fa8d68378a1ffab31 Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov <arvidj...@gmail.com> Date: Tue, 26 Jul 2016 20:38:58 +0300 Subject: [PATCH] dns: fix buffer overflow for data->addresses in recv_hook We may get more than one response before exiting out of loop in grub_net_dns_lookup, but buffer was allocated for the first response only, so storing answers from subsequent replies wrote past allocated size. We never really use more than the very first address during lookup so there is little point in collecting all of them. Just quit early if we already have some reply. Code needs serious redesign to actually collect multiple answers and select the best fit according to requested type (IPv4 or IPv6). Reported and tested by Michael Chang <mch...@suse.com> --- grub-core/net/dns.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c index 89741dd..5d9afe0 100644 --- a/grub-core/net/dns.c +++ b/grub-core/net/dns.c @@ -238,6 +238,15 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), char *redirect_save = NULL; grub_uint32_t ttl_all = ~0U; + /* Code apparently assumed that only one packet is received as response. + We may get multiple responses due to network condition, so check here + and quit early. */ + if (*data->addresses) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + head = (struct dns_header *) nb->data; ptr = (grub_uint8_t *) (head + 1); if (ptr >= nb->tail) -- 2.6.6 ++++++ 0001-misc-fix-invalid-character-recongition-in-strto-l.patch ++++++ >From 0155e49166494624e9fb6ef113ed2c16d4accbb3 Mon Sep 17 00:00:00 2001 From: Michael Chang <mch...@suse.com> Date: Fri, 29 Jul 2016 17:41:27 +0800 Subject: [PATCH 1/8] misc: fix invalid character recongition in strto*l From: Aaron Miller <aaronmil...@fb.com> Would previously allow digits larger than the base and didn't check that subtracting the difference from 0-9 to lowercase letters for characters larger than 9 didn't result in a value lower than 9, which allowed the parses: ` = 9, _ = 8, ^ = 7, ] = 6, \ = 5, and [ = 4 --- grub-core/kern/misc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c index d1a54df..3a14d67 100644 --- a/grub-core/kern/misc.c +++ b/grub-core/kern/misc.c @@ -394,9 +394,13 @@ grub_strtoull (const char *str, char **end, int base) if (digit > 9) { digit += '0' - 'a' + 10; - if (digit >= (unsigned long) base) + /* digit <= 9 check is needed to keep chars larger than + '9' but less than 'a' from being read as numbers */ + if (digit >= (unsigned long) base || digit <= 9) break; } + if (digit >= (unsigned long) base) + break; found = 1; -- 2.6.6 ++++++ 0002-net-read-bracketed-ipv6-addrs-and-port-numbers.patch ++++++ >From 4a00be0176a459fa6e199f2709eabbe8dc0d7979 Mon Sep 17 00:00:00 2001 From: Michael Chang <mch...@suse.com> Date: Fri, 29 Jul 2016 17:41:38 +0800 Subject: [PATCH 2/8] net: read bracketed ipv6 addrs and port numbers From: Aaron Miller <aaronmil...@fb.com> Allow specifying port numbers for http and tftp paths, and allow ipv6 addresses to be recognized with brackets around them, which is required to specify a port number --- grub-core/net/http.c | 21 ++++++++++--- grub-core/net/net.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--- grub-core/net/tftp.c | 6 +++- include/grub/net.h | 1 + 4 files changed, 104 insertions(+), 10 deletions(-) diff --git a/grub-core/net/http.c b/grub-core/net/http.c index 5aa4ad3..f182d7b 100644 --- a/grub-core/net/http.c +++ b/grub-core/net/http.c @@ -312,12 +312,14 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial) int i; struct grub_net_buff *nb; grub_err_t err; + char* server = file->device->net->server; + int port = file->device->net->port; nb = grub_netbuff_alloc (GRUB_NET_TCP_RESERVE_SIZE + sizeof ("GET ") - 1 + grub_strlen (data->filename) + sizeof (" HTTP/1.1\r\nHost: ") - 1 - + grub_strlen (file->device->net->server) + + grub_strlen (server) + sizeof (":XXXXXXXXXX") + sizeof ("\r\nUser-Agent: " PACKAGE_STRING "\r\n") - 1 + sizeof ("Range: bytes=XXXXXXXXXXXXXXXXXXXX" @@ -356,7 +358,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial) sizeof (" HTTP/1.1\r\nHost: ") - 1); ptr = nb->tail; - err = grub_netbuff_put (nb, grub_strlen (file->device->net->server)); + err = grub_netbuff_put (nb, grub_strlen (server)); if (err) { grub_netbuff_free (nb); @@ -365,6 +367,15 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial) grub_memcpy (ptr, file->device->net->server, grub_strlen (file->device->net->server)); + if (port) + { + ptr = nb->tail; + grub_snprintf ((char *) ptr, + sizeof (":XXXXXXXXXX"), + ":%d", + port); + } + ptr = nb->tail; err = grub_netbuff_put (nb, sizeof ("\r\nUser-Agent: " PACKAGE_STRING "\r\n") @@ -390,8 +401,10 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial) grub_netbuff_put (nb, 2); grub_memcpy (ptr, "\r\n", 2); - data->sock = grub_net_tcp_open (file->device->net->server, - HTTP_PORT, http_receive, + grub_dprintf ("http", "opening path %s on host %s TCP port %d\n", + data->filename, server, port ? port : HTTP_PORT); + data->sock = grub_net_tcp_open (server, + port ? port : HTTP_PORT, http_receive, http_err, http_err, file); if (!data->sock) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 10773fc..5cc0d2f 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -437,6 +437,12 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest) grub_uint16_t newip[8]; const char *ptr = val; int word, quaddot = -1; + int bracketed = 0; + + if (ptr[0] == '[') { + bracketed = 1; + ptr++; + } if (ptr[0] == ':' && ptr[1] != ':') return 0; @@ -475,6 +481,9 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest) grub_memset (&newip[quaddot], 0, (7 - word) * sizeof (newip[0])); } grub_memcpy (ip, newip, 16); + if (bracketed && *ptr == ']') { + ptr++; + } if (rest) *rest = ptr; return 1; @@ -1260,8 +1269,10 @@ grub_net_open_real (const char *name) { grub_net_app_level_t proto; const char *protname, *server; + char *host; grub_size_t protnamelen; int try; + int port = 0; if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0) { @@ -1299,6 +1310,72 @@ grub_net_open_real (const char *name) return NULL; } + char* port_start; + /* ipv6 or port specified? */ + if ((port_start = grub_strchr (server, ':'))) + { + char* ipv6_begin; + if((ipv6_begin = grub_strchr (server, '['))) + { + char* ipv6_end = grub_strchr (server, ']'); + if(!ipv6_end) + { + grub_error (GRUB_ERR_NET_BAD_ADDRESS, + N_("mismatched [ in address")); + return NULL; + } + /* port number after bracketed ipv6 addr */ + if(ipv6_end[1] == ':') + { + port = grub_strtoul (ipv6_end + 2, NULL, 10); + if(port > 65535) + { + grub_error (GRUB_ERR_NET_BAD_ADDRESS, + N_("bad port number")); + return NULL; + } + } + host = grub_strndup (ipv6_begin, (ipv6_end - ipv6_begin) + 1); + } + else + { + if (grub_strchr (port_start + 1, ':')) + { + int iplen = grub_strlen (server); + /* bracket bare ipv6 addrs */ + host = grub_malloc (iplen + 3); + if(!host) + { + return NULL; + } + host[0] = '['; + grub_memcpy (host + 1, server, iplen); + host[iplen + 1] = ']'; + host[iplen + 2] = '\0'; + } + else + { + /* hostname:port or ipv4:port */ + port = grub_strtol (port_start + 1, NULL, 10); + if(port > 65535) + { + grub_error (GRUB_ERR_NET_BAD_ADDRESS, + N_("bad port number")); + return NULL; + } + host = grub_strndup (server, port_start - server); + } + } + } + else + { + host = grub_strdup (server); + } + if (!host) + { + return NULL; + } + for (try = 0; try < 2; try++) { FOR_NET_APP_LEVEL (proto) @@ -1308,14 +1385,13 @@ grub_net_open_real (const char *name) { grub_net_t ret = grub_zalloc (sizeof (*ret)); if (!ret) - return NULL; - ret->protocol = proto; - ret->server = grub_strdup (server); - if (!ret->server) { - grub_free (ret); + grub_free (host); return NULL; } + ret->protocol = proto; + ret->port = port; + ret->server = host; ret->fs = &grub_net_fs; return ret; } diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 7d90bf6..a0817a0 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -314,6 +314,7 @@ tftp_open (struct grub_file *file, const char *filename) grub_err_t err; grub_uint8_t *nbd; grub_net_network_level_address_t addr; + int port = file->device->net->port; data = grub_zalloc (sizeof (*data)); if (!data) @@ -382,13 +383,16 @@ tftp_open (struct grub_file *file, const char *filename) err = grub_net_resolve_address (file->device->net->server, &addr); if (err) { + grub_dprintf ("tftp", "file_size is %llu, block_size is %llu\n", + (unsigned long long)data->file_size, + (unsigned long long)data->block_size); destroy_pq (data); grub_free (data); return err; } data->sock = grub_net_udp_open (addr, - TFTP_SERVER_PORT, tftp_receive, + port ? port : TFTP_SERVER_PORT, tftp_receive, file); if (!data->sock) { diff --git a/include/grub/net.h b/include/grub/net.h index 2192fa1..ccc169c 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -270,6 +270,7 @@ typedef struct grub_net { char *server; char *name; + int port; grub_net_app_level_t protocol; grub_net_packets_t packs; grub_off_t offset; -- 2.6.6 ++++++ 0003-bootp-New-net_bootp6-command.patch ++++++ ++++ 1118 lines (skipped) ++++++ 0004-efinet-UEFI-IPv6-PXE-support.patch ++++++ >From ca482c7c1efe5faf792bf0912a116ea8e0642e24 Mon Sep 17 00:00:00 2001 From: Michael Chang <mch...@suse.com> Date: Wed, 15 Apr 2015 14:48:30 +0800 Subject: [PATCH 4/8] efinet: UEFI IPv6 PXE support When grub2 image is booted from UEFI IPv6 PXE, the DHCPv6 Reply packet is cached in firmware buffer which can be obtained by PXE Base Code protocol. The network interface can be setup through the parameters in that obtained packet. Signed-off-by: Michael Chang <mch...@suse.com> Signed-off-by: Ken Lin <ken....@hpe.com> --- grub-core/net/drivers/efi/efinet.c | 24 +++++++++++++---- include/grub/efi/api.h | 55 +++++++++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c index 5388f95..fc90415 100644 --- a/grub-core/net/drivers/efi/efinet.c +++ b/grub-core/net/drivers/efi/efinet.c @@ -378,11 +378,25 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, if (! pxe) continue; pxe_mode = pxe->mode; - grub_net_configure_by_dhcp_ack (card->name, card, 0, - (struct grub_net_bootp_packet *) - &pxe_mode->dhcp_ack, - sizeof (pxe_mode->dhcp_ack), - 1, device, path); + + if (pxe_mode->using_ipv6) + { + grub_net_configure_by_dhcpv6_reply (card->name, card, 0, + (struct grub_net_dhcp6_packet *) + &pxe_mode->dhcp_ack, + sizeof (pxe_mode->dhcp_ack), + 1, device, path); + if (grub_errno) + grub_print_error (); + } + else + { + grub_net_configure_by_dhcp_ack (card->name, card, 0, + (struct grub_net_bootp_packet *) + &pxe_mode->dhcp_ack, + sizeof (pxe_mode->dhcp_ack), + 1, device, path); + } return; } } diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h index c7c9f0e..92f9b5a 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h @@ -1452,14 +1452,67 @@ typedef struct grub_efi_simple_text_output_interface grub_efi_simple_text_output typedef grub_uint8_t grub_efi_pxe_packet_t[1472]; +typedef struct { + grub_uint8_t addr[4]; +} grub_efi_pxe_ipv4_address_t; + +typedef struct { + grub_uint8_t addr[16]; +} grub_efi_pxe_ipv6_address_t; + +typedef struct { + grub_uint8_t addr[32]; +} grub_efi_pxe_mac_address_t; + +typedef union { + grub_uint32_t addr[4]; + grub_efi_pxe_ipv4_address_t v4; + grub_efi_pxe_ipv6_address_t v6; +} grub_efi_pxe_ip_address_t; + +#define GRUB_EFI_PXE_BASE_CODE_MAX_IPCNT 8 +typedef struct { + grub_uint8_t filters; + grub_uint8_t ip_cnt; + grub_uint16_t reserved; + grub_efi_pxe_ip_address_t ip_list[GRUB_EFI_PXE_BASE_CODE_MAX_IPCNT]; +} grub_efi_pxe_ip_filter_t; + +typedef struct { + grub_efi_pxe_ip_address_t ip_addr; + grub_efi_pxe_mac_address_t mac_addr; +} grub_efi_pxe_arp_entry_t; + +typedef struct { + grub_efi_pxe_ip_address_t ip_addr; + grub_efi_pxe_ip_address_t subnet_mask; + grub_efi_pxe_ip_address_t gw_addr; +} grub_efi_pxe_route_entry_t; + + +#define GRUB_EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES 8 +#define GRUB_EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES 8 + typedef struct grub_efi_pxe_mode { - grub_uint8_t unused[52]; + grub_uint8_t started; + grub_uint8_t ipv6_available; + grub_uint8_t ipv6_supported; + grub_uint8_t using_ipv6; + grub_uint8_t unused[16]; + grub_efi_pxe_ip_address_t station_ip; + grub_efi_pxe_ip_address_t subnet_mask; grub_efi_pxe_packet_t dhcp_discover; grub_efi_pxe_packet_t dhcp_ack; grub_efi_pxe_packet_t proxy_offer; grub_efi_pxe_packet_t pxe_discover; grub_efi_pxe_packet_t pxe_reply; + grub_efi_pxe_packet_t pxe_bis_reply; + grub_efi_pxe_ip_filter_t ip_filter; + grub_uint32_t arp_cache_entries; + grub_efi_pxe_arp_entry_t arp_cache[GRUB_EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES]; + grub_uint32_t route_table_entries; + grub_efi_pxe_route_entry_t route_table[GRUB_EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES]; } grub_efi_pxe_mode_t; typedef struct grub_efi_pxe -- 2.6.6 ++++++ 0005-grub.texi-Add-net_bootp6-doument.patch ++++++ >From 2c997c8c058b41d3a59a81f2bf654288b7cdf8f2 Mon Sep 17 00:00:00 2001 From: Michael Chang <mch...@suse.com> Date: Tue, 5 May 2015 14:19:24 +0800 Subject: [PATCH 5/8] grub.texi: Add net_bootp6 doument Update grub documentation for net_bootp6 command. Signed-off-by: Michael Chang <mch...@suse.com> Signed-off-by: Ken Lin <ken....@hpe.com> --- docs/grub.texi | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/grub.texi b/docs/grub.texi index 82f6fa4..60b4aa0 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -5173,6 +5173,7 @@ See @uref{http://wiki.xen.org/wiki/XSM} for more detail. * net_add_dns:: Add a DNS server * net_add_route:: Add routing entry * net_bootp:: Perform a bootp autoconfiguration +* net_bootp6:: Perform a DHCPv6 autoconfiguration * net_del_addr:: Remove IP address from interface * net_del_dns:: Remove a DNS server * net_del_route:: Remove a route entry @@ -5254,6 +5255,22 @@ Sets environment variable @samp{net_}@var{<card>}@samp{_dhcp_extensionspath} @end deffn +@node net_bootp6 +@subsection net_bootp6 + +@deffn Command net_bootp6 [@var{card}] +Perform configuration of @var{card} using DHCPv6 protocol. If no card name is +specified, try to configure all existing cards. If configuration was +successful, interface with name @var{card}@samp{:dhcp6} and configured address +is added to @var{card}. + +@table @samp +@item 1 (Domain Name Server) +Adds all servers from option value to the list of servers used during name +resolution. +@end table + +@end deffn @node net_del_addr @subsection net_del_addr -- 2.6.6 ++++++ 0006-bootp-Add-processing-DHCPACK-packet-from-HTTP-Boot.patch ++++++ >From 8191aae462f8b755972a0a801f4adbdd6ecaa66c Mon Sep 17 00:00:00 2001 From: Michael Chang <mch...@suse.com> Date: Thu, 14 Jul 2016 18:45:14 +0800 Subject: [PATCH 6/8] bootp: Add processing DHCPACK packet from HTTP Boot The vendor class identifier with the string "HTTPClient" is used to denote the packet as responding to HTTP boot request. In DHCP4 config, the filename for HTTP boot is the URL of the boot file while for PXE boot it is the path to the boot file. As a consequence, the next-server becomes obseleted because the HTTP URL already contains the server address for the boot file. For DHCP6 config, there's no difference definition in existing config as dhcp6.bootfile-url can be used to specify URL for both HTTP and PXE boot file. This patch adds processing for "HTTPClient" vendor class identifier in DHCPACK packet by treating it as HTTP format, not as the PXE format. Signed-off-by: Michael Chang <mch...@suse.com> Signed-off-by: Ken Lin <ken....@hpe.com> --- grub-core/net/bootp.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++-- include/grub/net.h | 1 + 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c index 81173b4..04f9f3d 100644 --- a/grub-core/net/bootp.c +++ b/grub-core/net/bootp.c @@ -207,6 +207,11 @@ parse_dhcp_vendor (const char *name, const void *vend, int limit, int *mask) taglength); break; + case GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER: + grub_env_set_net_property (name, "vendor_class_identifier", (const char *) ptr, + taglength); + break; + case GRUB_NET_BOOTP_EXTENSIONS_PATH: grub_env_set_net_property (name, "extensionspath", (const char *) ptr, taglength); @@ -281,6 +286,66 @@ grub_net_configure_by_dhcp_ack (const char *name, } #endif + if (size > OFFSET_OF (vendor, bp)) + { + char *cidvar; + const char *cid; + + parse_dhcp_vendor (name, &bp->vendor, size - OFFSET_OF (vendor, bp), &mask); + cidvar = grub_xasprintf ("net_%s_%s", name, "vendor_class_identifier"); + cid = grub_env_get (cidvar); + grub_free (cidvar); + + if (cid && grub_strcmp (cid, "HTTPClient") == 0) + { + char *proto, *ip, *pa; + + if (!dissect_url (bp->boot_file, &proto, &ip, &pa)) + return inter; + + grub_env_set_net_property (name, "boot_file", pa, grub_strlen (pa)); + if (is_def) + { + grub_net_default_server = grub_strdup (ip); + grub_env_set ("net_default_interface", name); + grub_env_export ("net_default_interface"); + } + if (device && !*device) + { + *device = grub_xasprintf ("%s,%s", proto, ip); + grub_print_error (); + } + if (path) + { + *path = grub_strdup (pa); + grub_print_error (); + if (*path) + { + char *slash; + slash = grub_strrchr (*path, '/'); + if (slash) + *slash = 0; + else + **path = 0; + } + } + grub_net_add_ipv4_local (inter, mask); + inter->dhcp_ack = grub_malloc (size); + if (inter->dhcp_ack) + { + grub_memcpy (inter->dhcp_ack, bp, size); + inter->dhcp_acklen = size; + } + else + grub_errno = GRUB_ERR_NONE; + + grub_free (proto); + grub_free (ip); + grub_free (pa); + return inter; + } + } + if (size > OFFSET_OF (boot_file, bp)) grub_env_set_net_property (name, "boot_file", bp->boot_file, sizeof (bp->boot_file)); @@ -342,8 +407,6 @@ grub_net_configure_by_dhcp_ack (const char *name, **path = 0; } } - if (size > OFFSET_OF (vendor, bp)) - parse_dhcp_vendor (name, &bp->vendor, size - OFFSET_OF (vendor, bp), &mask); grub_net_add_ipv4_local (inter, mask); inter->dhcp_ack = grub_malloc (size); diff --git a/include/grub/net.h b/include/grub/net.h index 38a3973..e4bf678 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -517,6 +517,7 @@ enum GRUB_NET_BOOTP_DOMAIN = 0x0f, GRUB_NET_BOOTP_ROOT_PATH = 0x11, GRUB_NET_BOOTP_EXTENSIONS_PATH = 0x12, + GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER = 0x3C, GRUB_NET_BOOTP_END = 0xff }; -- 2.6.6 ++++++ 0007-efinet-Setting-network-from-UEFI-device-path.patch ++++++ >From 369df8e3006000a4acacc674f5882d8729781811 Mon Sep 17 00:00:00 2001 From: Michael Chang <mch...@suse.com> Date: Sun, 10 Jul 2016 23:46:31 +0800 Subject: [PATCH 7/8] efinet: Setting network from UEFI device path The PXE Base Code protocol used to obtain cached PXE DHCPACK packet is no longer provided for HTTP Boot. Instead, we have to get the HTTP boot information from the device path nodes defined in following UEFI Specification sections. 9.3.5.12 IPv4 Device Path 9.3.5.13 IPv6 Device Path 9.3.5.23 Uniform Resource Identifiers (URI) Device Path This patch basically does: include/grub/efi/api.h: Add new structure of Uniform Resource Identifiers (URI) Device Path grub-core/net/drivers/efi/efinet.c: Check if PXE Base Code is available, if not it will try to obtain the netboot information from the device path where the image booted from. The DHCPACK packet is recoverd from the information in device patch and feed into the same DHCP packet processing functions to ensure the network interface is setting up the same way it used to be. Signed-off-by: Michael Chang <mch...@suse.com> Signed-off-by: Ken Lin <ken....@hpe.com> --- grub-core/net/drivers/efi/efinet.c | 268 +++++++++++++++++++++++++++++++++++-- include/grub/efi/api.h | 11 ++ 2 files changed, 270 insertions(+), 9 deletions(-) diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c index fc90415..2d3b00f 100644 --- a/grub-core/net/drivers/efi/efinet.c +++ b/grub-core/net/drivers/efi/efinet.c @@ -23,6 +23,7 @@ #include <grub/efi/api.h> #include <grub/efi/efi.h> #include <grub/i18n.h> +#include <grub/net/netbuff.h> GRUB_MOD_LICENSE ("GPLv3+"); @@ -324,6 +325,221 @@ grub_efinet_findcards (void) grub_free (handles); } +static struct grub_net_buff * +grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *use_ipv6) +{ + grub_efi_uint16_t uri_len; + grub_efi_device_path_t *ldp, *ddp; + grub_efi_uri_device_path_t *uri_dp; + struct grub_net_buff *nb; + grub_err_t err; + + ddp = grub_efi_duplicate_device_path (dp); + ldp = grub_efi_find_last_device_path (ddp); + + if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE + || GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_URI_DEVICE_PATH_SUBTYPE) + { + grub_free (ddp); + return NULL; + } + + uri_len = GRUB_EFI_DEVICE_PATH_LENGTH (ldp) > 4 ? GRUB_EFI_DEVICE_PATH_LENGTH (ldp) - 4 : 0; + + if (!uri_len) + { + grub_free (ddp); + return NULL; + } + + uri_dp = (grub_efi_uri_device_path_t *) ldp; + + ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; + ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; + ldp->length = sizeof (*ldp); + + ldp = grub_efi_find_last_device_path (ddp); + + if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE + || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE + && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE)) + { + grub_free (ddp); + return NULL; + } + + nb = grub_netbuff_alloc (512); + if (!nb) + return NULL; + + if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE) + { + grub_efi_ipv4_device_path_t *ipv4 = (grub_efi_ipv4_device_path_t *) ldp; + struct grub_net_bootp_packet *bp; + grub_uint8_t *ptr; + + bp = (struct grub_net_bootp_packet *) nb->tail; + err = grub_netbuff_put (nb, sizeof (*bp) + 4); + if (err) + { + grub_free (ddp); + grub_netbuff_free (nb); + return NULL; + } + + if (sizeof(bp->boot_file) < uri_len) + { + grub_free (ddp); + grub_netbuff_free (nb); + return NULL; + } + grub_memcpy (bp->boot_file, uri_dp->uri, uri_len); + grub_memcpy (&bp->your_ip, ipv4->local_ip_address, sizeof (bp->your_ip)); + grub_memcpy (&bp->server_ip, ipv4->remote_ip_address, sizeof (bp->server_ip)); + + bp->vendor[0] = GRUB_NET_BOOTP_RFC1048_MAGIC_0; + bp->vendor[1] = GRUB_NET_BOOTP_RFC1048_MAGIC_1; + bp->vendor[2] = GRUB_NET_BOOTP_RFC1048_MAGIC_2; + bp->vendor[3] = GRUB_NET_BOOTP_RFC1048_MAGIC_3; + + ptr = nb->tail; + err = grub_netbuff_put (nb, sizeof (ipv4->subnet_mask) + 2); + if (err) + { + grub_free (ddp); + grub_netbuff_free (nb); + return NULL; + } + *ptr++ = GRUB_NET_BOOTP_NETMASK; + *ptr++ = sizeof (ipv4->subnet_mask); + grub_memcpy (ptr, ipv4->subnet_mask, sizeof (ipv4->subnet_mask)); + + ptr = nb->tail; + err = grub_netbuff_put (nb, sizeof (ipv4->gateway_ip_address) + 2); + if (err) + { + grub_free (ddp); + grub_netbuff_free (nb); + return NULL; + } + *ptr++ = GRUB_NET_BOOTP_ROUTER; + *ptr++ = sizeof (ipv4->gateway_ip_address); + grub_memcpy (ptr, ipv4->gateway_ip_address, sizeof (ipv4->gateway_ip_address)); + + ptr = nb->tail; + err = grub_netbuff_put (nb, sizeof ("HTTPClient") + 1); + if (err) + { + grub_free (ddp); + grub_netbuff_free (nb); + return NULL; + } + *ptr++ = GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER; + *ptr++ = sizeof ("HTTPClient") - 1; + grub_memcpy (ptr, "HTTPClient", sizeof ("HTTPClient") - 1); + + ptr = nb->tail; + err = grub_netbuff_put (nb, 1); + if (err) + { + grub_free (ddp); + grub_netbuff_free (nb); + return NULL; + } + *ptr = GRUB_NET_BOOTP_END; + *use_ipv6 = 0; + + ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; + ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; + ldp->length = sizeof (*ldp); + ldp = grub_efi_find_last_device_path (ddp); + + if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE) + { + grub_efi_mac_address_device_path_t *mac = (grub_efi_mac_address_device_path_t *) ldp; + bp->hw_type = mac->if_type; + bp->hw_len = sizeof (bp->mac_addr); + grub_memcpy (bp->mac_addr, mac->mac_address, bp->hw_len); + } + } + else + { + grub_efi_ipv6_device_path_t *ipv6 = (grub_efi_ipv6_device_path_t *) ldp; + + struct grub_net_dhcp6_packet *d6p; + struct grub_net_dhcp6_option *opt; + struct grub_net_dhcp6_option_iana *iana; + struct grub_net_dhcp6_option_iaaddr *iaaddr; + + d6p = (struct grub_net_dhcp6_packet *)nb->tail; + err = grub_netbuff_put (nb, sizeof(*d6p)); + if (err) + { + grub_free (ddp); + grub_netbuff_free (nb); + return NULL; + } + d6p->message_type = GRUB_NET_DHCP6_REPLY; + + opt = (struct grub_net_dhcp6_option *)nb->tail; + err = grub_netbuff_put (nb, sizeof(*opt)); + if (err) + { + grub_free (ddp); + grub_netbuff_free (nb); + return NULL; + } + opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IA_NA); + opt->len = grub_cpu_to_be16_compile_time (sizeof(*iana) + sizeof(*opt) + sizeof(*iaaddr)); + + err = grub_netbuff_put (nb, sizeof(*iana)); + if (err) + { + grub_free (ddp); + grub_netbuff_free (nb); + return NULL; + } + + opt = (struct grub_net_dhcp6_option *)nb->tail; + err = grub_netbuff_put (nb, sizeof(*opt)); + if (err) + { + grub_free (ddp); + grub_netbuff_free (nb); + return NULL; + } + opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IAADDR); + opt->len = grub_cpu_to_be16_compile_time (sizeof (*iaaddr)); + + iaaddr = (struct grub_net_dhcp6_option_iaaddr *)nb->tail; + err = grub_netbuff_put (nb, sizeof(*iaaddr)); + if (err) + { + grub_free (ddp); + grub_netbuff_free (nb); + return NULL; + } + grub_memcpy (iaaddr->addr, ipv6->local_ip_address, sizeof(ipv6->local_ip_address)); + + opt = (struct grub_net_dhcp6_option *)nb->tail; + err = grub_netbuff_put (nb, sizeof(*opt) + uri_len); + if (err) + { + grub_free (ddp); + grub_netbuff_free (nb); + return NULL; + } + opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_BOOTFILE_URL); + opt->len = grub_cpu_to_be16 (uri_len); + grub_memcpy (opt->data, uri_dp->uri, uri_len); + + *use_ipv6 = 1; + } + + grub_free (ddp); + return nb; +} + static void grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, char **path) @@ -340,6 +556,11 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, grub_efi_device_path_t *cdp; struct grub_efi_pxe *pxe; struct grub_efi_pxe_mode *pxe_mode; + grub_uint8_t *packet_buf; + grub_size_t packet_bufsz ; + int ipv6; + struct grub_net_buff *nb = NULL; + if (card->driver != &efidriver) continue; cdp = grub_efi_get_device_path (card->efi_handle); @@ -359,11 +580,21 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, ldp = grub_efi_find_last_device_path (dp); if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE - && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE)) + && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE + && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)) continue; dup_dp = grub_efi_duplicate_device_path (dp); if (!dup_dp) continue; + + if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_URI_DEVICE_PATH_SUBTYPE) + { + dup_ldp = grub_efi_find_last_device_path (dup_dp); + dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; + dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; + dup_ldp->length = sizeof (*dup_ldp); + } + dup_ldp = grub_efi_find_last_device_path (dup_dp); dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; @@ -375,16 +606,31 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, } pxe = grub_efi_open_protocol (hnd, &pxe_io_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); - if (! pxe) - continue; - pxe_mode = pxe->mode; + if (!pxe) + { + nb = grub_efinet_create_dhcp_ack_from_device_path (dp, &ipv6); + if (!nb) + { + grub_print_error (); + continue; + } + packet_buf = nb->head; + packet_bufsz = nb->tail - nb->head; + } + else + { + pxe_mode = pxe->mode; + packet_buf = (grub_uint8_t *) &pxe_mode->dhcp_ack; + packet_bufsz = sizeof (pxe_mode->dhcp_ack); + ipv6 = pxe_mode->using_ipv6; + } - if (pxe_mode->using_ipv6) + if (ipv6) { grub_net_configure_by_dhcpv6_reply (card->name, card, 0, (struct grub_net_dhcp6_packet *) - &pxe_mode->dhcp_ack, - sizeof (pxe_mode->dhcp_ack), + packet_buf, + packet_bufsz, 1, device, path); if (grub_errno) grub_print_error (); @@ -393,10 +639,14 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, { grub_net_configure_by_dhcp_ack (card->name, card, 0, (struct grub_net_bootp_packet *) - &pxe_mode->dhcp_ack, - sizeof (pxe_mode->dhcp_ack), + packet_buf, + packet_bufsz, 1, device, path); } + + if (nb) + grub_netbuff_free (nb); + return; } } diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h index 92f9b5a..d5a1256 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h @@ -825,6 +825,8 @@ struct grub_efi_ipv4_device_path grub_efi_uint16_t remote_port; grub_efi_uint16_t protocol; grub_efi_uint8_t static_ip_address; + grub_efi_ipv4_address_t gateway_ip_address; + grub_efi_ipv4_address_t subnet_mask; } GRUB_PACKED; typedef struct grub_efi_ipv4_device_path grub_efi_ipv4_device_path_t; @@ -879,6 +881,15 @@ struct grub_efi_sata_device_path } GRUB_PACKED; typedef struct grub_efi_sata_device_path grub_efi_sata_device_path_t; +#define GRUB_EFI_URI_DEVICE_PATH_SUBTYPE 24 + +struct grub_efi_uri_device_path +{ + grub_efi_device_path_t header; + grub_efi_uint8_t uri[0]; +} GRUB_PACKED; +typedef struct grub_efi_uri_device_path grub_efi_uri_device_path_t; + #define GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE 10 /* Media Device Path. */ -- 2.6.6 ++++++ 0008-efinet-Setting-DNS-server-from-UEFI-protocol.patch ++++++ >From 0c7ae6d7527d08e54a6eeebddb6c5c697c4b37d2 Mon Sep 17 00:00:00 2001 From: Michael Chang <mch...@suse.com> Date: Thu, 14 Jul 2016 17:48:45 +0800 Subject: [PATCH 8/8] 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 <mch...@suse.com> Signed-off-by: Ken Lin <ken....@hpe.com> --- grub-core/net/drivers/efi/efinet.c | 163 +++++++++++++++++++++++++++++++++++++ include/grub/efi/api.h | 76 +++++++++++++++++ 2 files changed, 239 insertions(+) diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c index 2d3b00f..82a28fb 100644 --- a/grub-core/net/drivers/efi/efinet.c +++ b/grub-core/net/drivers/efi/efinet.c @@ -30,6 +30,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); /* GUID. */ static grub_efi_guid_t net_io_guid = GRUB_EFI_SIMPLE_NETWORK_GUID; static grub_efi_guid_t pxe_io_guid = GRUB_EFI_PXE_GUID; +static grub_efi_guid_t ip4_config_guid = GRUB_EFI_IP4_CONFIG2_PROTOCOL_GUID; +static grub_efi_guid_t ip6_config_guid = GRUB_EFI_IP6_CONFIG_PROTOCOL_GUID; static grub_err_t send_card_buffer (struct grub_net_card *dev, @@ -325,6 +327,125 @@ grub_efinet_findcards (void) grub_free (handles); } +static grub_efi_handle_t +grub_efi_locate_device_path (grub_efi_guid_t *protocol, grub_efi_device_path_t *device_path, + grub_efi_device_path_t **r_device_path) +{ + grub_efi_handle_t handle; + grub_efi_status_t status; + + status = efi_call_3 (grub_efi_system_table->boot_services->locate_device_path, + protocol, &device_path, &handle); + + if (status != GRUB_EFI_SUCCESS) + return 0; + + if (r_device_path) + *r_device_path = device_path; + + return handle; +} + +static grub_efi_ipv4_address_t * +grub_dns_server_ip4_address (grub_efi_device_path_t *dp, grub_efi_uintn_t *num_dns) +{ + grub_efi_handle_t hnd; + grub_efi_status_t status; + grub_efi_ip4_config2_protocol_t *conf; + grub_efi_ipv4_address_t *addrs; + grub_efi_uintn_t data_size = 1 * sizeof (grub_efi_ipv4_address_t); + + hnd = grub_efi_locate_device_path (&ip4_config_guid, dp, NULL); + + if (!hnd) + return 0; + + conf = grub_efi_open_protocol (hnd, &ip4_config_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); + + if (!conf) + return 0; + + addrs = grub_malloc (data_size); + if (!addrs) + return 0; + + status = efi_call_4 (conf->get_data, conf, + GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER, + &data_size, addrs); + + if (status == GRUB_EFI_BUFFER_TOO_SMALL) + { + grub_free (addrs); + addrs = grub_malloc (data_size); + if (!addrs) + return 0; + + status = efi_call_4 (conf->get_data, conf, + GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER, + &data_size, addrs); + } + + if (status != GRUB_EFI_SUCCESS) + { + grub_free (addrs); + return 0; + } + + *num_dns = data_size / sizeof (grub_efi_ipv4_address_t); + return addrs; +} + +static grub_efi_ipv6_address_t * +grub_dns_server_ip6_address (grub_efi_device_path_t *dp, grub_efi_uintn_t *num_dns) +{ + grub_efi_handle_t hnd; + grub_efi_status_t status; + grub_efi_ip6_config_protocol_t *conf; + grub_efi_ipv6_address_t *addrs; + grub_efi_uintn_t data_size = 1 * sizeof (grub_efi_ipv6_address_t); + + hnd = grub_efi_locate_device_path (&ip6_config_guid, dp, NULL); + + if (!hnd) + return 0; + + conf = grub_efi_open_protocol (hnd, &ip6_config_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); + + if (!conf) + return 0; + + addrs = grub_malloc (data_size); + if (!addrs) + return 0; + + status = efi_call_4 (conf->get_data, conf, + GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER, + &data_size, addrs); + + if (status == GRUB_EFI_BUFFER_TOO_SMALL) + { + grub_free (addrs); + addrs = grub_malloc (data_size); + if (!addrs) + return 0; + + status = efi_call_4 (conf->get_data, conf, + GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER, + &data_size, addrs); + } + + if (status != GRUB_EFI_SUCCESS) + { + grub_free (addrs); + return 0; + } + + *num_dns = data_size / sizeof (grub_efi_ipv6_address_t); + return addrs; +} + static struct grub_net_buff * grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *use_ipv6) { @@ -377,6 +498,8 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u grub_efi_ipv4_device_path_t *ipv4 = (grub_efi_ipv4_device_path_t *) ldp; struct grub_net_bootp_packet *bp; grub_uint8_t *ptr; + grub_efi_ipv4_address_t *dns; + grub_efi_uintn_t num_dns; bp = (struct grub_net_bootp_packet *) nb->tail; err = grub_netbuff_put (nb, sizeof (*bp) + 4); @@ -438,6 +561,25 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u *ptr++ = sizeof ("HTTPClient") - 1; grub_memcpy (ptr, "HTTPClient", sizeof ("HTTPClient") - 1); + dns = grub_dns_server_ip4_address (dp, &num_dns); + if (dns) + { + grub_efi_uintn_t size_dns = sizeof (*dns) * num_dns; + + ptr = nb->tail; + err = grub_netbuff_put (nb, size_dns + 2); + if (err) + { + grub_free (ddp); + grub_netbuff_free (nb); + return NULL; + } + *ptr++ = GRUB_NET_BOOTP_DNS; + *ptr++ = size_dns; + grub_memcpy (ptr, dns, size_dns); + grub_free (dns); + } + ptr = nb->tail; err = grub_netbuff_put (nb, 1); if (err) @@ -470,6 +612,8 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u struct grub_net_dhcp6_option *opt; struct grub_net_dhcp6_option_iana *iana; struct grub_net_dhcp6_option_iaaddr *iaaddr; + grub_efi_ipv6_address_t *dns; + grub_efi_uintn_t num_dns; d6p = (struct grub_net_dhcp6_packet *)nb->tail; err = grub_netbuff_put (nb, sizeof(*d6p)); @@ -533,6 +677,25 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u opt->len = grub_cpu_to_be16 (uri_len); grub_memcpy (opt->data, uri_dp->uri, uri_len); + dns = grub_dns_server_ip6_address (dp, &num_dns); + if (dns) + { + grub_efi_uintn_t size_dns = sizeof (*dns) * num_dns; + + opt = (struct grub_net_dhcp6_option *)nb->tail; + err = grub_netbuff_put (nb, sizeof(*opt) + size_dns); + if (err) + { + grub_free (ddp); + grub_netbuff_free (nb); + return NULL; + } + opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_DNS_SERVERS); + opt->len = grub_cpu_to_be16 (size_dns); + grub_memcpy (opt->data, dns, size_dns); + grub_free (dns); + } + *use_ipv6 = 1; } diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h index d5a1256..99ba068 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h @@ -334,6 +334,16 @@ { 0x8B, 0x8C, 0xE2, 0x1B, 0x01, 0xAE, 0xF2, 0xB7 } \ } +#define GRUB_EFI_IP4_CONFIG2_PROTOCOL_GUID \ + { 0x5b446ed1, 0xe30b, 0x4faa, \ + { 0x87, 0x1a, 0x36, 0x54, 0xec, 0xa3, 0x60, 0x80 } \ + } + +#define GRUB_EFI_IP6_CONFIG_PROTOCOL_GUID \ + { 0x937fe521, 0x95ae, 0x4d1a, \ + { 0x89, 0x29, 0x48, 0xbc, 0xd9, 0x0a, 0xd3, 0x1a } \ + } + struct grub_efi_sal_system_table { grub_uint32_t signature; @@ -1749,6 +1759,72 @@ struct grub_efi_block_io }; typedef struct grub_efi_block_io grub_efi_block_io_t; +enum grub_efi_ip4_config2_data_type { + GRUB_EFI_IP4_CONFIG2_DATA_TYPE_INTERFACEINFO, + GRUB_EFI_IP4_CONFIG2_DATA_TYPE_POLICY, + GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS, + GRUB_EFI_IP4_CONFIG2_DATA_TYPE_GATEWAY, + GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER, + GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MAXIMUM +}; +typedef enum grub_efi_ip4_config2_data_type grub_efi_ip4_config2_data_type_t; + +struct grub_efi_ip4_config2_protocol +{ + grub_efi_status_t (*set_data) (struct grub_efi_ip4_config2_protocol *this, + grub_efi_ip4_config2_data_type_t data_type, + grub_efi_uintn_t data_size, + void *data); + + grub_efi_status_t (*get_data) (struct grub_efi_ip4_config2_protocol *this, + grub_efi_ip4_config2_data_type_t data_type, + grub_efi_uintn_t *data_size, + void *data); + + grub_efi_status_t (*register_data_notify) (struct grub_efi_ip4_config2_protocol *this, + grub_efi_ip4_config2_data_type_t data_type, + grub_efi_event_t event); + + grub_efi_status_t (*unregister_datanotify) (struct grub_efi_ip4_config2_protocol *this, + grub_efi_ip4_config2_data_type_t data_type, + grub_efi_event_t event); +}; +typedef struct grub_efi_ip4_config2_protocol grub_efi_ip4_config2_protocol_t; + +enum grub_efi_ip6_config_data_type { + GRUB_EFI_IP6_CONFIG_DATA_TYPE_INTERFACEINFO, + GRUB_EFI_IP6_CONFIG_DATA_TYPE_ALT_INTERFACEID, + GRUB_EFI_IP6_CONFIG_DATA_TYPE_POLICY, + GRUB_EFI_IP6_CONFIG_DATA_TYPE_DUP_ADDR_DETECT_TRANSMITS, + GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS, + GRUB_EFI_IP6_CONFIG_DATA_TYPE_GATEWAY, + GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER, + GRUB_EFI_IP6_CONFIG_DATA_TYPE_MAXIMUM +}; +typedef enum grub_efi_ip6_config_data_type grub_efi_ip6_config_data_type_t; + +struct grub_efi_ip6_config_protocol +{ + grub_efi_status_t (*set_data) (struct grub_efi_ip6_config_protocol *this, + grub_efi_ip6_config_data_type_t data_type, + grub_efi_uintn_t data_size, + void *data); + + grub_efi_status_t (*get_data) (struct grub_efi_ip6_config_protocol *this, + grub_efi_ip6_config_data_type_t data_type, + grub_efi_uintn_t *data_size, + void *data); + + grub_efi_status_t (*register_data_notify) (struct grub_efi_ip6_config_protocol *this, + grub_efi_ip6_config_data_type_t data_type, + grub_efi_event_t event); + + grub_efi_status_t (*unregister_datanotify) (struct grub_efi_ip6_config_protocol *this, + grub_efi_ip6_config_data_type_t data_type, + grub_efi_event_t event); +}; +typedef struct grub_efi_ip6_config_protocol grub_efi_ip6_config_protocol_t; + #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \ || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) -- 2.6.6 ++++++ grub.default ++++++ --- /var/tmp/diff_new_pack.rsNj0l/_old 2016-08-11 18:53:09.000000000 +0200 +++ /var/tmp/diff_new_pack.rsNj0l/_new 2016-08-11 18:53:09.000000000 +0200 @@ -9,7 +9,7 @@ GRUB_HIDDEN_TIMEOUT=0 GRUB_HIDDEN_TIMEOUT_QUIET=true GRUB_TIMEOUT=10 -GRUB_CMDLINE_LINUX_DEFAULT="quiet splash=silent" +GRUB_CMDLINE_LINUX_DEFAULT="" GRUB_CMDLINE_LINUX="" # Uncomment to automatically save last booted menu entry in GRUB2 environment ++++++ grub2-fix-multi-device-root-kernel-argument.patch ++++++ Index: grub-2.02~beta2/util/grub.d/10_linux.in =================================================================== --- grub-2.02~beta2.orig/util/grub.d/10_linux.in +++ grub-2.02~beta2/util/grub.d/10_linux.in @@ -45,12 +45,14 @@ esac # btrfs may reside on multiple devices. We cannot pass them as value of root= parameter # and mounting btrfs requires user space scanning, so force UUID in this case. -if [ "x${GRUB_DEVICE_UUID}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \ +if ( [ "x${GRUB_DEVICE_UUID}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \ || ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \ - || ( test -e "${GRUB_DEVICE}" && uses_abstraction "${GRUB_DEVICE}" lvm ); then + || uses_abstraction "${GRUB_DEVICE}" lvm ) && test -e "${GRUB_DEVICE}"; then LINUX_ROOT_DEVICE=${GRUB_DEVICE} else - LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID} + if [ "x${GRUB_DEVICE_UUID}" != "x" ]; then + LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID} + fi fi if [ "x$GRUB_CONMODE" != "x" ]; then Index: grub-2.02~beta2/util/grub.d/20_linux_xen.in =================================================================== --- grub-2.02~beta2.orig/util/grub.d/20_linux_xen.in +++ grub-2.02~beta2/util/grub.d/20_linux_xen.in @@ -55,12 +55,14 @@ esac # btrfs may reside on multiple devices. We cannot pass them as value of root= parameter # and mounting btrfs requires user space scanning, so force UUID in this case. -if [ "x${GRUB_DEVICE_UUID}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \ +if ( [ "x${GRUB_DEVICE_UUID}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \ || ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \ - || ( test -e "${GRUB_DEVICE}" && uses_abstraction "${GRUB_DEVICE}" lvm ); then + || uses_abstraction "${GRUB_DEVICE}" lvm ) && test -e "${GRUB_DEVICE}"; then LINUX_ROOT_DEVICE=${GRUB_DEVICE} else - LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID} + if [ "x${GRUB_DEVICE_UUID}" != "x" ]; then + LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID} + fi fi # Allow overriding GRUB_CMDLINE_LINUX and GRUB_CMDLINE_LINUX_DEFAULT. ++++++ grub2-suse-remove-linux-root-param.patch ++++++ Index: grub-2.02~beta2/util/grub-mkconfig.in =================================================================== --- grub-2.02~beta2.orig/util/grub-mkconfig.in +++ grub-2.02~beta2/util/grub-mkconfig.in @@ -261,7 +261,8 @@ export GRUB_DEFAULT \ GRUB_CMDLINE_LINUX_RECOVERY \ GRUB_USE_LINUXEFI \ SUSE_BTRFS_SNAPSHOT_BOOTING \ - SUSE_CMDLINE_XENEFI + SUSE_CMDLINE_XENEFI \ + SUSE_REMOVE_LINUX_ROOT_PARAM if test "x${grub_cfg}" != "x"; then rm -f "${grub_cfg}.new" Index: grub-2.02~beta2/util/grub.d/10_linux.in =================================================================== --- grub-2.02~beta2.orig/util/grub.d/10_linux.in +++ grub-2.02~beta2/util/grub.d/10_linux.in @@ -66,7 +66,7 @@ case x"$GRUB_FS" in else rootsubvol="`make_system_path_relative_to_its_root /`" rootsubvol="${rootsubvol#/}" - if [ "x${rootsubvol}" != x ]; then + if [ "x${rootsubvol}" != x ] && [ "x$SUSE_REMOVE_LINUX_ROOT_PARAM" != "xtrue" ]; then GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}" fi fi;; @@ -77,6 +77,10 @@ case x"$GRUB_FS" in ;; esac +if [ "x$SUSE_REMOVE_LINUX_ROOT_PARAM" = "xtrue" ]; then + LINUX_ROOT_DEVICE="" +fi + title_correction_code= hotkey=1 Index: grub-2.02~beta2/util/grub.d/20_linux_xen.in =================================================================== --- grub-2.02~beta2.orig/util/grub.d/20_linux_xen.in +++ grub-2.02~beta2/util/grub.d/20_linux_xen.in @@ -80,7 +80,7 @@ case x"$GRUB_FS" in else rootsubvol="`make_system_path_relative_to_its_root /`" rootsubvol="${rootsubvol#/}" - if [ "x${rootsubvol}" != x ]; then + if [ "x${rootsubvol}" != x ] && [ "x$SUSE_REMOVE_LINUX_ROOT_PARAM" != "xtrue" ]; then GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}" fi fi;; @@ -91,6 +91,10 @@ case x"$GRUB_FS" in ;; esac +if [ "x$SUSE_REMOVE_LINUX_ROOT_PARAM" = "xtrue" ]; then + LINUX_ROOT_DEVICE="" +fi + title_correction_code= if [ -d /sys/firmware/efi ]; then Index: grub-2.02~beta2/util/s390x/zipl2grub.pl.in =================================================================== --- grub-2.02~beta2.orig/util/s390x/zipl2grub.pl.in +++ grub-2.02~beta2/util/s390x/zipl2grub.pl.in @@ -361,9 +361,13 @@ while ( <IN> ) { } else { $v = ""; } - if ($k eq "GRUB_DEVICE" && $v !~ /^UUID/ && ! -e $v) { - s{root=\@$k\@}{}g; - next; + if ($k eq "GRUB_DEVICE") { + if (($v !~ /^UUID/ && ! -e $v) || + (exists( $C{SUSE_REMOVE_LINUX_ROOT_PARAM}) && + $C{SUSE_REMOVE_LINUX_ROOT_PARAM} eq "true")) { + s{root=\@$k\@}{}g; + next; + } } s{\@$k\@}{$v}g; } ++++++ grub2-zipl-setup-fix-btrfs-multipledev.patch ++++++ Index: grub-2.02~beta2/util/s390x/zipl2grub.pl.in =================================================================== --- grub-2.02~beta2.orig/util/s390x/zipl2grub.pl.in +++ grub-2.02~beta2/util/s390x/zipl2grub.pl.in @@ -361,6 +361,10 @@ while ( <IN> ) { } else { $v = ""; } + if ($k eq "GRUB_DEVICE" && $v !~ /^UUID/ && ! -e $v) { + s{root=\@$k\@}{}g; + next; + } s{\@$k\@}{$v}g; } Info( 2, $_);