From 4fe85bdb06ee2f8e746f2143a7d8b663dbb7105b Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Nov 02 2019 20:07:59 +0000 Subject: import grub2-2.02-0.81.el7 --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8173666 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +SOURCES/grub-2.02~beta2.tar.xz +SOURCES/unifont-5.1.20080820.pcf.gz diff --git a/.grub2.metadata b/.grub2.metadata new file mode 100644 index 0000000..a7bf121 --- /dev/null +++ b/.grub2.metadata @@ -0,0 +1,2 @@ +1bf580f1e8bce4909a7ac7ca485cee02b00ed383 SOURCES/grub-2.02~beta2.tar.xz +87f8600ba24e521b5d20bdf6c4b71af8ae861e3a SOURCES/unifont-5.1.20080820.pcf.gz diff --git a/SOURCES/0001-fix-EFI-detection-on-Windows.patch b/SOURCES/0001-fix-EFI-detection-on-Windows.patch new file mode 100644 index 0000000..e2f5d18 --- /dev/null +++ b/SOURCES/0001-fix-EFI-detection-on-Windows.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrey Borzenkov +Date: Wed, 25 Dec 2013 22:36:28 +0400 +Subject: [PATCH] fix EFI detection on Windows + +We are on legacy BIOS if GetFirmwareEnvironmentVariable fails (returns +zero) *and* extended error information is ERROR_INVALID_FUNCTION. + +Cf. http://msdn.microsoft.com/en-us/library/windows/desktop/ms724325%28v=vs.85%29.aspx +--- + grub-core/osdep/windows/platform.c | 2 +- + ChangeLog | 5 +++++ + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/grub-core/osdep/windows/platform.c b/grub-core/osdep/windows/platform.c +index f2b9d714329..d217efe1704 100644 +--- a/grub-core/osdep/windows/platform.c ++++ b/grub-core/osdep/windows/platform.c +@@ -100,7 +100,7 @@ get_platform (void) + + if (!func_GetFirmwareEnvironmentVariableW (L"BootOrder", GRUB_EFI_GLOBAL_VARIABLE_GUID_WINDOWS_STR, + buffer, sizeof (buffer)) +- && GetLastError () != ERROR_INVALID_FUNCTION) ++ && GetLastError () == ERROR_INVALID_FUNCTION) + { + platform = PLAT_BIOS; + return; +diff --git a/ChangeLog b/ChangeLog +index 41bcebfb321..21ec1c77c57 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2013-12-25 Andrey Borzenkov ++ ++ * grub-core/osdep/windows/platform.c (get_platform): Fix EFI ++ detection. ++ + 2013-12-24 Vladimir Serbinenko + + * configure.ac: Set version to 2.02~beta2. diff --git a/SOURCES/0002-grub-core-kern-arm-cache_armv6.S-Remove-.arch-direct.patch b/SOURCES/0002-grub-core-kern-arm-cache_armv6.S-Remove-.arch-direct.patch new file mode 100644 index 0000000..bb7a145 --- /dev/null +++ b/SOURCES/0002-grub-core-kern-arm-cache_armv6.S-Remove-.arch-direct.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Wed, 25 Dec 2013 23:31:42 +0100 +Subject: [PATCH] * grub-core/kern/arm/cache_armv6.S: Remove .arch directive. + + As these functions are used on pre-ARMv6 CPUs as well we don't want + to make assembler assume that architecture is higher than default one. +--- + grub-core/kern/arm/cache_armv6.S | 1 - + ChangeLog | 7 +++++++ + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/grub-core/kern/arm/cache_armv6.S b/grub-core/kern/arm/cache_armv6.S +index 39da1dfc606..dfaded0eb30 100644 +--- a/grub-core/kern/arm/cache_armv6.S ++++ b/grub-core/kern/arm/cache_armv6.S +@@ -22,7 +22,6 @@ + .text + .syntax unified + .arm +- .arch armv6 + + # define DMB mcr p15, 0, r0, c7, c10, 5 + # define DSB mcr p15, 0, r0, c7, c10, 4 +diff --git a/ChangeLog b/ChangeLog +index 21ec1c77c57..153bc43c1c5 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,10 @@ ++2013-12-25 Vladimir Serbinenko ++ ++ * grub-core/kern/arm/cache_armv6.S: Remove .arch directive. ++ ++ As these functions are used on pre-ARMv6 CPUs as well we don't want ++ to make assembler assume that architecture is higher than default one. ++ + 2013-12-25 Andrey Borzenkov + + * grub-core/osdep/windows/platform.c (get_platform): Fix EFI diff --git a/SOURCES/0003-INSTALL-Cross-compiling-the-GRUB-Fix-some-spelling-m.patch b/SOURCES/0003-INSTALL-Cross-compiling-the-GRUB-Fix-some-spelling-m.patch new file mode 100644 index 0000000..e4d3972 --- /dev/null +++ b/SOURCES/0003-INSTALL-Cross-compiling-the-GRUB-Fix-some-spelling-m.patch @@ -0,0 +1,85 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Colin Watson +Date: Fri, 27 Dec 2013 03:03:32 +0000 +Subject: [PATCH] * INSTALL (Cross-compiling the GRUB): Fix some spelling + mistakes. * docs/grub.texi (Getting the source code): Likewise. + +--- + ChangeLog | 5 +++++ + INSTALL | 10 +++++----- + docs/grub-dev.texi | 8 ++++---- + 3 files changed, 14 insertions(+), 9 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index 153bc43c1c5..bbb0f31532d 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2013-12-27 Colin Watson ++ ++ * INSTALL (Cross-compiling the GRUB): Fix some spelling mistakes. ++ * docs/grub.texi (Getting the source code): Likewise. ++ + 2013-12-25 Vladimir Serbinenko + + * grub-core/kern/arm/cache_armv6.S: Remove .arch directive. +diff --git a/INSTALL b/INSTALL +index afc957ca997..db12530dff3 100644 +--- a/INSTALL ++++ b/INSTALL +@@ -140,7 +140,7 @@ If build and host are different make check isn't available. + If build and host are different man pages are not generated. + + As an example imagine you have a build system running on FreeBSD on sparc +-which prepares packages for developpers running amd64 GNU/Linux laptop and ++which prepares packages for developers running amd64 GNU/Linux laptop and + they need to make images for ARM board running U-boot. In this case: + + build=sparc64-freebsd +@@ -149,7 +149,7 @@ target=arm-uboot + + For this example the configure line might look like (more details below) + (some options are optional and included here for completeness but some rarely +-used options are omited): ++used options are omitted): + + ./configure BUILD_CC=gcc BUILD_FREETYPE=freetype-config --host=amd64-linux-gnu + CC=amd64-linux-gnu-gcc CFLAGS="-g -O2" FREETYPE=amd64-linux-gnu-freetype-config +@@ -196,9 +196,9 @@ corresponding platform are not needed for the platform in question. + 11. TARGET_RANLIB= for ranlib for target. + + - Additionally for emu, for host and target. +- 1. SDL is looked for in stadard linker directories (-lSDL) (optional) +- 2. libpciaccess is looked for in stadard linker directories (-lpciaccess) (optional) +- 3. libusb is looked for in stadard linker directories (-lusb) (optional) ++ 1. SDL is looked for in standard linker directories (-lSDL) (optional) ++ 2. libpciaccess is looked for in standard linker directories (-lpciaccess) (optional) ++ 3. libusb is looked for in standard linker directories (-lusb) (optional) + + - Platform-agnostic tools and data. + 1. make is the tool you execute after ./configure. +diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi +index c796850522a..7c6244cdb71 100644 +--- a/docs/grub-dev.texi ++++ b/docs/grub-dev.texi +@@ -108,16 +108,16 @@ The branches available are: + + @table @samp + @item master +- Main developpement branch. ++ Main development branch. + @item grub-legacy + GRUB 0.97 codebase. Kept for reference and legal reasons + @item multiboot + Multiboot specfication + @item multiboot2 + Multiboot2 specfication +-@item developper branches +- Prefixed with developper name. Every developper of a team manages his own branches. +- Developper branches do not need changelog entries. ++@item developer branches ++ Prefixed with developer name. Every developer of a team manages his own branches. ++ Developer branches do not need changelog entries. + @end table + + Once you have used @kbd{git clone} to fetch an initial copy of a branch, you diff --git a/SOURCES/0004-NEWS-First-draft-of-2.02-entry.patch b/SOURCES/0004-NEWS-First-draft-of-2.02-entry.patch new file mode 100644 index 0000000..1141167 --- /dev/null +++ b/SOURCES/0004-NEWS-First-draft-of-2.02-entry.patch @@ -0,0 +1,149 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Colin Watson +Date: Fri, 27 Dec 2013 03:05:38 +0000 +Subject: [PATCH] * NEWS: First draft of 2.02 entry. + +--- + ChangeLog | 4 +++ + NEWS | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 123 insertions(+) + +diff --git a/ChangeLog b/ChangeLog +index bbb0f31532d..82dc61d24c9 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2013-12-27 Colin Watson ++ ++ * NEWS: First draft of 2.02 entry. ++ + 2013-12-27 Colin Watson + + * INSTALL (Cross-compiling the GRUB): Fix some spelling mistakes. +diff --git a/NEWS b/NEWS +index 4bb5f98010d..577d9fd7323 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,3 +1,122 @@ ++New in 2.02: ++ ++* New/improved filesystem and disk support: ++ * Big-endian UFS1. ++ * Experimental 64-bit ext2 support. ++ * Various fixes for non-512-byte sector devices. ++ * New `proc' filesystem framework, used by LUKS disks. ++ * Fix DM-RAID partition handling. ++ * New `nativedisk' command to switch from firmware to native disk drivers. ++ * Compressed HFS+. ++ * DragonFly BSD labels. ++ * CBFS (coreboot). ++ * Handle partitioned LVM properly. ++ * Use LVM UUIDs whenever possible. ++ * GPT PReP. ++ * New `progress' module that shows progress information while reading ++ files. ++ ++* New/improved terminal and video support: ++ * Monochrome text (matching `hercules' in GRUB Legacy). ++ * Morse code output using system speaker. ++ * `spkmodem' output (simple data protocol using system speaker). ++ * Handle Japanese special keys. ++ * coreboot framebuffer. ++ * Serial on ARC. ++ * Native vt100 handling for grub-emu, replacing the use of the curses ++ library. ++ * New gfxmenu options for terminal window positioning, theme background ++ image handling, and scrollbar padding, plus `item_pixmap_style' and ++ `highlight_overlay'. ++ * Support several more image types (paletted and greyscale). ++ ++* Boot protocol improvements: ++ * Support Apple FAT binaries on non-Apple platforms. ++ * Improve FreeDOS direct loading support compatibility. ++ * Enable `linux16' on all x86 platforms, not just BIOS. ++ * New TrueCrypt ISO loader. ++ ++* New/improved network support: ++ * New variables `net_default_*' containing properties of the default ++ interface. ++ * Autoload `http' and `tftp' modules if necessary. ++ * Improve TFTP robustness. ++ * Parse `nd' disk names in GRUB Legacy configuration files. ++ * Issue separate DNS queries for IPv4 and IPv6. ++ ++* New/improved platform support: ++ * New `efifwsetup' and `lsefi' commands on EFI platforms. ++ * New `cmosclean', `cmosdump', and `cmosset' commands on platforms with ++ CMOS support. ++ * New `cbmemc', `coreboot_boottime', and `lscoreboot' commands on ++ coreboot. ++ * Improve opcode parsing in ACPI halt implementation. ++ * Use the TSC as a possible time source on i386-ieee1275. ++ * Merge PowerPC grub-mkrescue implementation with the common one. ++ * Support grub-mkrescue on i386-ieee1275, sparc64, bootinfo machines such ++ as pSeries, and mips-arc. ++ * Make grub-mkrescue better support Apple Intel Macs on CD. ++ * Enable GRUB Legacy configuration file parsing on EFI. ++ * Support halt for Loongson 2E. ++ * ARM U-Boot and EFI ports. ++ * Reorganise platform-dependent code in utilities to avoid #ifdef mess. ++ * AROS and Haiku support for userspace utilities. ++ * Xen PV port. ++ * Fix EFI stack alignment. ++ * ARM64 EFI port. ++ * On Linux, read partition start offsets from sysfs if possible. ++ * New grub-macbless utility, and better integration with Mac firmware in ++ grub-install. ++ * Support Yeeloong 3A. ++ * Add `cpuid --pae' option to detect Physical Address Extension on x86. ++ ++* Security: ++ * Add optional facility to enforce that all files read by the core image ++ from disk have a valid detached digital signature. ++ ++* Performance: ++ * Avoid costly division operations in many places. ++ * New boot time analysis framework (`./configure --enable-boot-time'). ++ * Initialise USB ports in parallel. ++ * New `testspeed' command to test file read speed. ++ ++* Scripting: ++ * New `eval' and `tr' commands. ++ * grub-script-check fails on scripts containing no commands. ++ ++* Installation and other utility improvements: ++ * Add option to compress files on installation or image creation. ++ * Using grub-reboot no longer requires setting `GRUB_DEFAULT=saved'. ++ * Support probing EFI System Partition (requires os-prober >= 1.58). ++ * Fix inconsistent use of `GRUB_CRYPTODISK_ENABLE' and ++ `GRUB_ENABLE_CRYPTODISK'; the latter is now used consistently. ++ * grub-mount handles symbolic links to directories. ++ * Support disabling submenus with `GRUB_DISABLE_SUBMENU' configuration key ++ for grub-mkconfig. ++ * grub-install, grub-mknetdir, grub-mkrescue, and grub-mkstandalone ++ rewritten in C. They should now work in supported non-Unix-like ++ environments. ++ * Reorganise timeout handling using new `timeout_style' environment ++ variable and `GRUB_TIMEOUT_STYLE' configuration key for grub-mkconfig. ++ Menu hotkeys pressed during a hidden timeout now boot the corresponding ++ menu entry immediately. ++ * New `file' command and grub-file utility to check file types. ++ * New syslinux configuration file parser. ++ ++* Build system: ++ * Remove all uses of nested functions; GRUB no longer requires an ++ executable stack. ++ * Fix documentation build with Texinfo >= 5.1. ++ * More robust and documented cross-compiling support. ++ * Partial clang support for some platforms. ++ * Eliminate the use of AutoGen. This allowed some performance ++ improvements to the build system. ++ * Fix build with FreeType >= 2.5.1. ++ * Make gentpl.py compatible with Python 3. It now requires at least ++ Python 2.6. ++ ++* Revision control moved to git. ++ + New in 2.00: + + * Appearance: diff --git a/SOURCES/0005-Merge-branch-master-of-git.sv.gnu.org-srv-git-grub.patch b/SOURCES/0005-Merge-branch-master-of-git.sv.gnu.org-srv-git-grub.patch new file mode 100644 index 0000000..6fd2f6f --- /dev/null +++ b/SOURCES/0005-Merge-branch-master-of-git.sv.gnu.org-srv-git-grub.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Fri, 27 Dec 2013 11:20:37 +0100 +Subject: [PATCH] Merge branch 'master' of git.sv.gnu.org:/srv/git/grub + +Conflicts: + ChangeLog +--- + ChangeLog | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index 82dc61d24c9..da3c2dfdf0a 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,19 +1,19 @@ +-2013-12-27 Colin Watson +- +- * NEWS: First draft of 2.02 entry. +- +-2013-12-27 Colin Watson +- +- * INSTALL (Cross-compiling the GRUB): Fix some spelling mistakes. +- * docs/grub.texi (Getting the source code): Likewise. +- +-2013-12-25 Vladimir Serbinenko ++2013-12-27 Vladimir Serbinenko + + * grub-core/kern/arm/cache_armv6.S: Remove .arch directive. + + As these functions are used on pre-ARMv6 CPUs as well we don't want + to make assembler assume that architecture is higher than default one. + ++2013-12-27 Colin Watson ++ ++ * NEWS: First draft of 2.02 entry. ++ ++2013-12-27 Colin Watson ++ ++ * INSTALL (Cross-compiling the GRUB): Fix some spelling mistakes. ++ * docs/grub.texi (Getting the source code): Likewise. ++ + 2013-12-25 Andrey Borzenkov + + * grub-core/osdep/windows/platform.c (get_platform): Fix EFI diff --git a/SOURCES/0006-NEWS-The-cmosclean-command-in-fact-dates-back-to-1.9.patch b/SOURCES/0006-NEWS-The-cmosclean-command-in-fact-dates-back-to-1.9.patch new file mode 100644 index 0000000..01dc202 --- /dev/null +++ b/SOURCES/0006-NEWS-The-cmosclean-command-in-fact-dates-back-to-1.9.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Colin Watson +Date: Sat, 28 Dec 2013 02:20:27 +0000 +Subject: [PATCH] * NEWS: The cmosclean command in fact dates back to 1.99. + Remove mention of it from 2.02. + +--- + ChangeLog | 5 +++++ + NEWS | 3 +-- + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index da3c2dfdf0a..c33856eab8d 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2013-12-28 Colin Watson ++ ++ * NEWS: The cmosclean command in fact dates back to 1.99. Remove ++ mention of it from 2.02. ++ + 2013-12-27 Vladimir Serbinenko + + * grub-core/kern/arm/cache_armv6.S: Remove .arch directive. +diff --git a/NEWS b/NEWS +index 577d9fd7323..b74c05f637f 100644 +--- a/NEWS ++++ b/NEWS +@@ -46,8 +46,7 @@ New in 2.02: + + * New/improved platform support: + * New `efifwsetup' and `lsefi' commands on EFI platforms. +- * New `cmosclean', `cmosdump', and `cmosset' commands on platforms with +- CMOS support. ++ * New `cmosdump' and `cmosset' commands on platforms with CMOS support. + * New `cbmemc', `coreboot_boottime', and `lscoreboot' commands on + coreboot. + * Improve opcode parsing in ACPI halt implementation. diff --git a/SOURCES/0007-remove-unused-error.h-from-kern-emu-misc.c.patch b/SOURCES/0007-remove-unused-error.h-from-kern-emu-misc.c.patch new file mode 100644 index 0000000..36b2004 --- /dev/null +++ b/SOURCES/0007-remove-unused-error.h-from-kern-emu-misc.c.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrey Borzenkov +Date: Sat, 28 Dec 2013 09:01:20 +0400 +Subject: [PATCH] remove unused error.h from kern/emu/misc.c + +Fixes compilation on mingw32, where include is apparently missing. +--- + grub-core/kern/emu/misc.c | 1 - + ChangeLog | 5 +++++ + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c +index 43471b4efe9..bb606da2803 100644 +--- a/grub-core/kern/emu/misc.c ++++ b/grub-core/kern/emu/misc.c +@@ -20,7 +20,6 @@ + #include + + #include +-#include + #include + #include + #include +diff --git a/ChangeLog b/ChangeLog +index c33856eab8d..0401f6154f8 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2013-12-28 Andrey Borzenkov ++ ++ * grub-core/kern/emu/misc.c: Remove unused error.h; fixes compilation ++ on mingw. ++ + 2013-12-28 Colin Watson + + * NEWS: The cmosclean command in fact dates back to 1.99. Remove diff --git a/SOURCES/0008-Don-t-abort-on-unavailable-coreboot-tables-if-not-ru.patch b/SOURCES/0008-Don-t-abort-on-unavailable-coreboot-tables-if-not-ru.patch new file mode 100644 index 0000000..c900a62 --- /dev/null +++ b/SOURCES/0008-Don-t-abort-on-unavailable-coreboot-tables-if-not-ru.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Sat, 28 Dec 2013 17:25:14 +0100 +Subject: [PATCH] Don't abort() on unavailable coreboot tables if not running + on coreboot. + +--- + grub-core/kern/i386/coreboot/cbtable.c | 2 +- + grub-core/kern/i386/coreboot/init.c | 5 +++++ + ChangeLog | 4 ++++ + 3 files changed, 10 insertions(+), 1 deletion(-) + +diff --git a/grub-core/kern/i386/coreboot/cbtable.c b/grub-core/kern/i386/coreboot/cbtable.c +index e3bb7b2e09d..1669bc0ca23 100644 +--- a/grub-core/kern/i386/coreboot/cbtable.c ++++ b/grub-core/kern/i386/coreboot/cbtable.c +@@ -55,7 +55,7 @@ grub_linuxbios_table_iterate (int (*hook) (grub_linuxbios_table_item_t, + if (check_signature (table_header)) + goto signature_found; + +- grub_fatal ("Could not find coreboot table\n"); ++ return 0; + + signature_found: + +diff --git a/grub-core/kern/i386/coreboot/init.c b/grub-core/kern/i386/coreboot/init.c +index 6b150b47d88..3314f027fec 100644 +--- a/grub-core/kern/i386/coreboot/init.c ++++ b/grub-core/kern/i386/coreboot/init.c +@@ -51,6 +51,7 @@ grub_exit (void) + + grub_addr_t grub_modbase = GRUB_KERNEL_I386_COREBOOT_MODULES_ADDR; + static grub_uint64_t modend; ++static int have_memory = 0; + + /* Helper for grub_machine_init. */ + static int +@@ -82,6 +83,8 @@ heap_init (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type, + + grub_mm_init_region ((void *) (grub_addr_t) begin, (grub_size_t) (end - begin)); + ++ have_memory = 1; ++ + return 0; + } + +@@ -97,6 +100,8 @@ grub_machine_init (void) + grub_vga_text_init (); + + grub_machine_mmap_iterate (heap_init, NULL); ++ if (!have_memory) ++ grub_fatal ("No memory found"); + + grub_video_coreboot_fb_late_init (); + +diff --git a/ChangeLog b/ChangeLog +index 0401f6154f8..ed6d77cc8ea 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2013-12-28 Vladimir Serbinenko ++ ++ Don't abort() on unavailable coreboot tables if not running on coreboot. ++ + 2013-12-28 Andrey Borzenkov + + * grub-core/kern/emu/misc.c: Remove unused error.h; fixes compilation diff --git a/SOURCES/0009-NEWS-Add-few-missing-entries.-Correct-existing-ones.patch b/SOURCES/0009-NEWS-Add-few-missing-entries.-Correct-existing-ones.patch new file mode 100644 index 0000000..6d567b4 --- /dev/null +++ b/SOURCES/0009-NEWS-Add-few-missing-entries.-Correct-existing-ones.patch @@ -0,0 +1,117 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Mon, 30 Dec 2013 06:49:15 +0100 +Subject: [PATCH] * NEWS: Add few missing entries. Correct existing ones. + +--- + ChangeLog | 4 ++++ + NEWS | 27 ++++++++++++++++++++++----- + 2 files changed, 26 insertions(+), 5 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index ed6d77cc8ea..db843006df9 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2013-12-30 Vladimir Serbinenko ++ ++ * NEWS: Add few missing entries. Correct existing ones. ++ + 2013-12-28 Vladimir Serbinenko + + Don't abort() on unavailable coreboot tables if not running on coreboot. +diff --git a/NEWS b/NEWS +index b74c05f637f..49a2459b6a0 100644 +--- a/NEWS ++++ b/NEWS +@@ -35,6 +35,8 @@ New in 2.02: + * Improve FreeDOS direct loading support compatibility. + * Enable `linux16' on all x86 platforms, not just BIOS. + * New TrueCrypt ISO loader. ++ * multiboot2 boot-services EFI specification. ++ * multiboot2 full-file specfication. + + * New/improved network support: + * New variables `net_default_*' containing properties of the default +@@ -44,11 +46,17 @@ New in 2.02: + * Parse `nd' disk names in GRUB Legacy configuration files. + * Issue separate DNS queries for IPv4 and IPv6. + ++* Coreboot improvements: ++ * CBFS support both in on-disk images (loopback) and flash. ++ * Ability to launch another payload from flash or disk ++ * Coreboot framebuffer ++ * CBMEMC support (both logging and inspecting logs) ++ * Inspecting coreboot timestamps. ++ * Inspecting coreboot tables. ++ + * New/improved platform support: + * New `efifwsetup' and `lsefi' commands on EFI platforms. + * New `cmosdump' and `cmosset' commands on platforms with CMOS support. +- * New `cbmemc', `coreboot_boottime', and `lscoreboot' commands on +- coreboot. + * Improve opcode parsing in ACPI halt implementation. + * Use the TSC as a possible time source on i386-ieee1275. + * Merge PowerPC grub-mkrescue implementation with the common one. +@@ -68,6 +76,7 @@ New in 2.02: + grub-install. + * Support Yeeloong 3A. + * Add `cpuid --pae' option to detect Physical Address Extension on x86. ++ * Support for USB debug dongles. + + * Security: + * Add optional facility to enforce that all files read by the core image +@@ -78,6 +87,7 @@ New in 2.02: + * New boot time analysis framework (`./configure --enable-boot-time'). + * Initialise USB ports in parallel. + * New `testspeed' command to test file read speed. ++ * Speed-up gfxterm by storing intermediate results in more compact format. + + * Scripting: + * New `eval' and `tr' commands. +@@ -95,6 +105,7 @@ New in 2.02: + * grub-install, grub-mknetdir, grub-mkrescue, and grub-mkstandalone + rewritten in C. They should now work in supported non-Unix-like + environments. ++ * Native mingw support, including ability to install on EFI under windows. + * Reorganise timeout handling using new `timeout_style' environment + variable and `GRUB_TIMEOUT_STYLE' configuration key for grub-mkconfig. + Menu hotkeys pressed during a hidden timeout now boot the corresponding +@@ -107,12 +118,19 @@ New in 2.02: + executable stack. + * Fix documentation build with Texinfo >= 5.1. + * More robust and documented cross-compiling support. +- * Partial clang support for some platforms. ++ * Partial clang support for some platforms (experimental). ++ * Partial mingw64 x86_64-efi compile support (highly experimental). ++ * Partial mingw32 i386-* (other than already present i386-pc) ++ compile support (highly experimental). + * Eliminate the use of AutoGen. This allowed some performance + improvements to the build system. ++ * Remove variable length arrays. ++ * OpenBSD compile and tools support (NetBSD and FreeBSD were already supported). + * Fix build with FreeType >= 2.5.1. + * Make gentpl.py compatible with Python 3. It now requires at least + Python 2.6. ++ * modinfo.sh contains build information now. ++ * Added many new tests to improve robustness. + + * Revision control moved to git. + +@@ -142,7 +160,6 @@ New in 2.00: + * IEEE1275 serial. + * EFI serial. + * Network stack for BIOS, IEEE1275, EMU and EFI, including TFTP, HTTP and DNS. +- * VBE on coreboot support. + + * New filesystem, filters and disks formats: + * DVH partition map. +@@ -166,7 +183,7 @@ New in 2.00: + * multidevice, mirrored and raidz(2,3) ZFS support. + * RAID LVM (internal RAIDing) support. + * ZFS crypto support. +- * ZLE and GZIP on ZFS support. ++ * ZLE, LZ4 and GZIP on ZFS support. + * Support ZFS up to 33. + * HFS string is now treated like mac-roman and not UTF-8 + * HFS mtime support. diff --git a/SOURCES/0010-strip-.eh_frame-section-from-arm64-efi-kernel.patch b/SOURCES/0010-strip-.eh_frame-section-from-arm64-efi-kernel.patch new file mode 100644 index 0000000..39b57e0 --- /dev/null +++ b/SOURCES/0010-strip-.eh_frame-section-from-arm64-efi-kernel.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrey Borzenkov +Date: Mon, 30 Dec 2013 12:56:19 +0000 +Subject: [PATCH] strip .eh_frame section from arm64-efi kernel + +Fixes grub-mkimage error "relocation 0x105 is not implemented yet." +--- + grub-core/Makefile.core.def | 2 +- + ChangeLog | 4 ++++ + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index c916246de27..42443bc00b9 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -66,7 +66,7 @@ kernel = { + arm_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; + + arm64_efi_ldflags = '-Wl,-r,-d'; +- arm64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; ++ arm64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame'; + + i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000'; +diff --git a/ChangeLog b/ChangeLog +index db843006df9..8c1ececa1ed 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2013-12-30 Andrey Borzenkov ++ ++ * grub-core/Makefile.core.def: strip .eh_frame section for arm64-efi. ++ + 2013-12-30 Vladimir Serbinenko + + * NEWS: Add few missing entries. Correct existing ones. diff --git a/SOURCES/0011-use-grub-boot-aa64.efi-for-boot-images-on-AArch64.patch b/SOURCES/0011-use-grub-boot-aa64.efi-for-boot-images-on-AArch64.patch new file mode 100644 index 0000000..ba4a9c9 --- /dev/null +++ b/SOURCES/0011-use-grub-boot-aa64.efi-for-boot-images-on-AArch64.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrey Borzenkov +Date: Tue, 7 Jan 2014 10:38:54 +0400 +Subject: [PATCH] use {grub,boot}aa64.efi for boot images on AArch64 + +According to UEFI 2.4 specification, default boot file name on AArch64 +is BOOTAA64.EFI (3.4.1.1 Removable Media Boot Behavior). Also set default +GRUB image name to grubaa64.efi to match it. +--- + util/grub-install.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/util/grub-install.c b/util/grub-install.c +index 8cfe0eaa2ef..4608b80fe05 100644 +--- a/util/grub-install.c ++++ b/util/grub-install.c +@@ -1091,7 +1091,7 @@ main (int argc, char *argv[]) + efi_file = "BOOTARM.EFI"; + break; + case GRUB_INSTALL_PLATFORM_ARM64_EFI: +- efi_file = "BOOTAARCH64.EFI"; ++ efi_file = "BOOTAA64.EFI"; + break; + default: + grub_util_error ("%s", _("You've found a bug")); +@@ -1118,7 +1118,7 @@ main (int argc, char *argv[]) + efi_file = "grubarm.efi"; + break; + case GRUB_INSTALL_PLATFORM_ARM64_EFI: +- efi_file = "grubarm64.efi"; ++ efi_file = "grubaa64.efi"; + break; + default: + efi_file = "grub.efi"; diff --git a/SOURCES/0012-fix-32-bit-compilation-on-MinGW-w64.patch b/SOURCES/0012-fix-32-bit-compilation-on-MinGW-w64.patch new file mode 100644 index 0000000..56f0178 --- /dev/null +++ b/SOURCES/0012-fix-32-bit-compilation-on-MinGW-w64.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrey Borzenkov +Date: Tue, 7 Jan 2014 18:43:02 +0400 +Subject: [PATCH] fix 32 bit compilation on MinGW-w64 + +Use _FILE_OFFSET_BITS macro to distinguish between native MinGW and +32 bit under MinGW-64. The latter does not require fseeko/ftello +redefinition which it already does in case of _FILE_OFFSET_BITS=64. +--- + include/grub/osdep/hostfile_windows.h | 3 +++ + ChangeLog | 5 +++++ + 2 files changed, 8 insertions(+) + +diff --git a/include/grub/osdep/hostfile_windows.h b/include/grub/osdep/hostfile_windows.h +index 36615b2c451..79efcfa5084 100644 +--- a/include/grub/osdep/hostfile_windows.h ++++ b/include/grub/osdep/hostfile_windows.h +@@ -69,8 +69,11 @@ enum grub_util_fd_open_flags_t + + #if defined (__MINGW32__) && !defined (__MINGW64__) + ++/* 32 bit on MinGW-64 already redefines them if _FILE_OFFSET_BITS=64 */ ++#if !defined(_FILE_OFFSET_BITS) + #define fseeko fseeko64 + #define ftello ftello64 ++#endif + + #endif + +diff --git a/ChangeLog b/ChangeLog +index 8c1ececa1ed..e87f0a7a4a4 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2014-01-07 Andrey Borzenkov ++ ++ * include/grub/osdep/hostfile_windows.h: Do not redefine fseeko/ftello ++ on MinGW-64 when compiling for 32 bits. ++ + 2013-12-30 Andrey Borzenkov + + * grub-core/Makefile.core.def: strip .eh_frame section for arm64-efi. diff --git a/SOURCES/0013-Change-grub-mkrescue-to-use-bootaa64.efi-too.patch b/SOURCES/0013-Change-grub-mkrescue-to-use-bootaa64.efi-too.patch new file mode 100644 index 0000000..53589b5 --- /dev/null +++ b/SOURCES/0013-Change-grub-mkrescue-to-use-bootaa64.efi-too.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrey Borzenkov +Date: Tue, 7 Jan 2014 20:34:25 +0400 +Subject: [PATCH] Change grub-mkrescue to use bootaa64.efi too + +Also add ChangeLog entry for previous change. +--- + util/grub-mkrescue.c | 2 +- + ChangeLog | 7 +++++++ + 2 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/util/grub-mkrescue.c b/util/grub-mkrescue.c +index 317879d0b50..0d03e55d20c 100644 +--- a/util/grub-mkrescue.c ++++ b/util/grub-mkrescue.c +@@ -663,7 +663,7 @@ main (int argc, char *argv[]) + make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_ARM_EFI, "arm-efi", imgname); + free (imgname); + +- imgname = grub_util_path_concat (2, efidir_efi_boot, "bootaarch64.efi"); ++ imgname = grub_util_path_concat (2, efidir_efi_boot, "bootaa64.efi"); + make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_ARM64_EFI, "arm64-efi", + imgname); + free (imgname); +diff --git a/ChangeLog b/ChangeLog +index e87f0a7a4a4..0b9fa05b2a0 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,10 @@ ++2014-01-07 Andrey Borzenkov ++ ++ * util/grub-install.c: Use bootaa64.efi instead of bootaarch64.efi on ++ arm64 to comply with EFI specification. Also use grubaa64.efi for ++ consistency. ++ * util/grub-mkrescue.c: Change to use bootaa64.efi too. ++ + 2014-01-07 Andrey Borzenkov + + * include/grub/osdep/hostfile_windows.h: Do not redefine fseeko/ftello diff --git a/SOURCES/0014-arm64-set-correct-length-of-device-path-end-entry.patch b/SOURCES/0014-arm64-set-correct-length-of-device-path-end-entry.patch new file mode 100644 index 0000000..39ed674 --- /dev/null +++ b/SOURCES/0014-arm64-set-correct-length-of-device-path-end-entry.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Leif Lindholm +Date: Tue, 7 Jan 2014 17:52:50 +0000 +Subject: [PATCH] arm64: set correct length of device path end entry + +The length of the Device Path End entry in the grub_linux_boot() +function was incorrectly set to 0. This triggers an assert failure +in debug builds of Tianocore. + +Set it to sizeof (grub_efi_device_path_t). +--- + grub-core/loader/arm64/linux.c | 2 +- + ChangeLog | 4 ++++ + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c +index 9d15aad625e..75ad871a81c 100644 +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -268,7 +268,7 @@ grub_linux_boot (void) + + mempath[1].header.type = GRUB_EFI_END_DEVICE_PATH_TYPE; + mempath[1].header.subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; +- mempath[1].header.length = 0; ++ mempath[1].header.length = sizeof (grub_efi_device_path_t); + + b = grub_efi_system_table->boot_services; + status = b->load_image (0, grub_efi_image_handle, +diff --git a/ChangeLog b/ChangeLog +index 0b9fa05b2a0..4ec5517bded 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2014-01-07 Leif Lindholm ++ ++ * grub-core/loader/arm64/linux.c: correctly set device path end length. ++ + 2014-01-07 Andrey Borzenkov + + * util/grub-install.c: Use bootaa64.efi instead of bootaarch64.efi on diff --git a/SOURCES/0015-Makefile.util.def-grub-macbless-Change-mansection-to.patch b/SOURCES/0015-Makefile.util.def-grub-macbless-Change-mansection-to.patch new file mode 100644 index 0000000..90ad43c --- /dev/null +++ b/SOURCES/0015-Makefile.util.def-grub-macbless-Change-mansection-to.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Colin Watson +Date: Wed, 8 Jan 2014 11:05:20 +0000 +Subject: [PATCH] * Makefile.util.def (grub-macbless): Change mansection to 8. + +--- + Makefile.util.def | 2 +- + ChangeLog | 4 ++++ + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/Makefile.util.def b/Makefile.util.def +index 985e76ca4e5..3c99be2b0ca 100644 +--- a/Makefile.util.def ++++ b/Makefile.util.def +@@ -405,7 +405,7 @@ program = { + program = { + name = grub-macbless; + installdir = sbin; +- mansection = 1; ++ mansection = 8; + common = util/grub-macbless.c; + common = grub-core/osdep/init.c; + common = grub-core/kern/emu/argp_common.c; +diff --git a/ChangeLog b/ChangeLog +index 4ec5517bded..b445f121586 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2014-01-08 Colin Watson ++ ++ * Makefile.util.def (grub-macbless): Change mansection to 8. ++ + 2014-01-07 Leif Lindholm + + * grub-core/loader/arm64/linux.c: correctly set device path end length. diff --git a/SOURCES/0016-add-part_apple-to-EFI-rescue-image-to-fix-missing-pr.patch b/SOURCES/0016-add-part_apple-to-EFI-rescue-image-to-fix-missing-pr.patch new file mode 100644 index 0000000..863584c --- /dev/null +++ b/SOURCES/0016-add-part_apple-to-EFI-rescue-image-to-fix-missing-pr.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrey Borzenkov +Date: Sun, 12 Jan 2014 15:29:21 +0400 +Subject: [PATCH] add part_apple to EFI rescue image to fix missing prefix + +On Mac rescue image is booted from HFS+ partition, so bootpath looks like +/ACPI(a0341d0,0)/PCI(1,1f)/ATAPI(0,0,0)/HD(3,5d1,ca3,0000000000000000,20,0)/EndEntire + +grub fails to find device for this path because it cannot scan partition +table. The simplest fix is to add part_apple by default. +--- + util/grub-mkrescue.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/util/grub-mkrescue.c b/util/grub-mkrescue.c +index 0d03e55d20c..34e0b7affb1 100644 +--- a/util/grub-mkrescue.c ++++ b/util/grub-mkrescue.c +@@ -653,11 +653,15 @@ main (int argc, char *argv[]) + make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_IA64_EFI, "ia64-efi", imgname); + free (imgname); + ++ grub_install_push_module ("part_apple"); + img64 = grub_util_path_concat (2, efidir_efi_boot, "bootx64.efi"); + make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_X86_64_EFI, "x86_64-efi", img64); ++ grub_install_pop_module (); + ++ grub_install_push_module ("part_apple"); + img32 = grub_util_path_concat (2, efidir_efi_boot, "bootia32.efi"); + make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_I386_EFI, "i386-efi", img32); ++ grub_install_pop_module (); + + imgname = grub_util_path_concat (2, efidir_efi_boot, "bootarm.efi"); + make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_ARM_EFI, "arm-efi", imgname); +@@ -707,7 +711,9 @@ main (int argc, char *argv[]) + free (efidir); + } + ++ grub_install_push_module ("part_apple"); + make_image_fwdisk (GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275, "powerpc-ieee1275", "powerpc-ieee1275/core.elf"); ++ grub_install_pop_module (); + + if (source_dirs[GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275]) + { diff --git a/SOURCES/0017-freebsd-hostdisk.c-is-only-ever-compiled-on-FreeBSD.patch b/SOURCES/0017-freebsd-hostdisk.c-is-only-ever-compiled-on-FreeBSD.patch new file mode 100644 index 0000000..3f346cf --- /dev/null +++ b/SOURCES/0017-freebsd-hostdisk.c-is-only-ever-compiled-on-FreeBSD.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Colin Watson +Date: Fri, 17 Jan 2014 02:30:52 +0000 +Subject: [PATCH] freebsd/hostdisk.c is only ever compiled on FreeBSD + +* grub-core/osdep/freebsd/hostdisk.c (grub_util_fd_open): Remove +redundant preprocessor conditional. +--- + grub-core/osdep/freebsd/hostdisk.c | 2 -- + ChangeLog | 5 +++++ + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/grub-core/osdep/freebsd/hostdisk.c b/grub-core/osdep/freebsd/hostdisk.c +index bd5fddb9150..eb202dcc831 100644 +--- a/grub-core/osdep/freebsd/hostdisk.c ++++ b/grub-core/osdep/freebsd/hostdisk.c +@@ -108,7 +108,6 @@ grub_util_fd_open (const char *os_dev, int flags) + + ret = open (os_dev, flags, S_IROTH | S_IRGRP | S_IRUSR | S_IWUSR); + +-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + if (! (sysctl_oldflags & 0x10) + && sysctlbyname ("kern.geom.debugflags", NULL , 0, &sysctl_oldflags, sysctl_size)) + { +@@ -116,7 +115,6 @@ grub_util_fd_open (const char *os_dev, int flags) + close (ret); + return GRUB_UTIL_FD_INVALID; + } +-#endif + + return ret; + } +diff --git a/ChangeLog b/ChangeLog +index b445f121586..6613b4ee52b 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2014-01-17 Colin Watson ++ ++ * grub-core/osdep/freebsd/hostdisk.c (grub_util_fd_open): Remove ++ redundant preprocessor conditional. ++ + 2014-01-08 Colin Watson + + * Makefile.util.def (grub-macbless): Change mansection to 8. diff --git a/SOURCES/0018-Prefer-more-portable-test-1-constructs.patch b/SOURCES/0018-Prefer-more-portable-test-1-constructs.patch new file mode 100644 index 0000000..0fa41cd --- /dev/null +++ b/SOURCES/0018-Prefer-more-portable-test-1-constructs.patch @@ -0,0 +1,106 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Colin Watson +Date: Fri, 17 Jan 2014 15:24:50 +0000 +Subject: [PATCH] Prefer more portable test(1) constructs + +* util/grub.d/00_header.in (make_timeout): Use && rather than test +-a. +* util/grub.d/10_windows.in: Likewise. +* util/grub.d/10_netbsd.in (netbsd_load_fs_module): Use || rather +than test -o. +* util/grub.d/30_os-prober.in: Use && rather than test -a, and || +rather than test -o. +--- + ChangeLog | 12 +++++++++++- + util/grub.d/00_header.in | 2 +- + util/grub.d/10_netbsd.in | 2 +- + util/grub.d/10_windows.in | 4 ++-- + util/grub.d/30_os-prober.in | 4 ++-- + 5 files changed, 17 insertions(+), 7 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index 6613b4ee52b..c8e95a6b98d 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,4 +1,14 @@ +-2014-01-17 Colin Watson ++2014-01-17 Colin Watson ++ ++ * util/grub.d/00_header.in (make_timeout): Use && rather than test ++ -a. ++ * util/grub.d/10_windows.in: Likewise. ++ * util/grub.d/10_netbsd.in (netbsd_load_fs_module): Use || rather ++ than test -o. ++ * util/grub.d/30_os-prober.in: Use && rather than test -a, and || ++ rather than test -o. ++ ++2014-01-17 Colin Watson + + * grub-core/osdep/freebsd/hostdisk.c (grub_util_fd_open): Remove + redundant preprocessor conditional. +diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in +index 0c82f231574..ce2ec819d8c 100644 +--- a/util/grub.d/00_header.in ++++ b/util/grub.d/00_header.in +@@ -285,7 +285,7 @@ make_timeout () + if [ "x${3}" != "x" ] ; then + timeout="${2}" + style="${3}" +- elif [ "x${1}" != "x" -a "x${1}" != "x0" ] ; then ++ elif [ "x${1}" != "x" ] && [ "x${1}" != "x0" ] ; then + # Handle the deprecated GRUB_HIDDEN_TIMEOUT scheme. + timeout="${1}" + if [ "x${2}" != "x0" ] ; then +diff --git a/util/grub.d/10_netbsd.in b/util/grub.d/10_netbsd.in +index 29a0e41a9a5..9988a42bc50 100644 +--- a/util/grub.d/10_netbsd.in ++++ b/util/grub.d/10_netbsd.in +@@ -69,7 +69,7 @@ netbsd_load_fs_module () + kversion=$(zcat -f "${kernel}" | strings | sed -n -e '/^@(#)NetBSD/ { s/^@(#)NetBSD \([0-9\.]*\) .*$/\1/g ; p ; q ; }') + kmodule="/stand/${karch}/${kversion}/modules/${kmod}/${kmod}.kmod" + +- if test -z "$karch" -o -z "$kversion" -o ! -f "${kmodule}"; then ++ if test -z "$karch" || test -z "$kversion" || test ! -f "${kmodule}"; then + return + fi + +diff --git a/util/grub.d/10_windows.in b/util/grub.d/10_windows.in +index 9025914f6cf..48bd955464b 100644 +--- a/util/grub.d/10_windows.in ++++ b/util/grub.d/10_windows.in +@@ -66,11 +66,11 @@ for drv in $drives ; do + osid= + + # Check for Vista bootmgr. +- if [ -f "$dir"/bootmgr -a -f "$dir"/boot/bcd ] ; then ++ if [ -f "$dir"/bootmgr ] && [ -f "$dir"/boot/bcd ] ; then + OS="$(gettext "Windows Vista/7 (loader)")" + osid=bootmgr + # Check for NTLDR. +- elif [ -f "$dir"/ntldr -a -f "$dir"/ntdetect.com -a -f "$dir"/boot.ini ] ; then ++ elif [ -f "$dir"/ntldr ] && [ -f "$dir"/ntdetect.com ] && [ -f "$dir"/boot.ini ] ; then + OS=`get_os_name_from_boot_ini "$dir"/boot.ini` || OS="$(gettext "Windows NT/2000/XP (loader)")" + osid=ntldr + needmap=t +diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in +index 0470e66853d..7cf8487d63a 100644 +--- a/util/grub.d/30_os-prober.in ++++ b/util/grub.d/30_os-prober.in +@@ -30,7 +30,7 @@ if [ "x${GRUB_DISABLE_OS_PROBER}" = "xtrue" ]; then + exit 0 + fi + +-if [ -z "`which os-prober 2> /dev/null`" -o -z "`which linux-boot-prober 2> /dev/null`" ] ; then ++if [ -z "`which os-prober 2> /dev/null`" ] || [ -z "`which linux-boot-prober 2> /dev/null`" ] ; then + # missing os-prober and/or linux-boot-prober + exit 0 + fi +@@ -119,7 +119,7 @@ for OS in ${OSPROBED} ; do + EXPUUID="${EXPUUID}@${DEVICE#*@}" + fi + +- if [ "x${GRUB_OS_PROBER_SKIP_LIST}" != "x" -a "x`echo ${GRUB_OS_PROBER_SKIP_LIST} | grep -i -e '\b'${EXPUUID}'\b'`" != "x" ] ; then ++ if [ "x${GRUB_OS_PROBER_SKIP_LIST}" != "x" ] && [ "x`echo ${GRUB_OS_PROBER_SKIP_LIST} | grep -i -e '\b'${EXPUUID}'\b'`" != "x" ] ; then + echo "Skipped ${LONGNAME} on ${DEVICE} by user request." >&2 + continue + fi diff --git a/SOURCES/0019-NEWS-Add-few-missing-entries.patch b/SOURCES/0019-NEWS-Add-few-missing-entries.patch new file mode 100644 index 0000000..53226a5 --- /dev/null +++ b/SOURCES/0019-NEWS-Add-few-missing-entries.patch @@ -0,0 +1,97 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Sat, 18 Jan 2014 16:31:10 +0100 +Subject: [PATCH] * NEWS: Add few missing entries. + +--- + ChangeLog | 4 ++++ + NEWS | 18 +++++++++++++++--- + 2 files changed, 19 insertions(+), 3 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index c8e95a6b98d..6a19f850448 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2014-01-18 Vladimir Serbinenko ++ ++ * NEWS: Add few missing entries. ++ + 2014-01-17 Colin Watson + + * util/grub.d/00_header.in (make_timeout): Use && rather than test +diff --git a/NEWS b/NEWS +index 49a2459b6a0..a61df942a35 100644 +--- a/NEWS ++++ b/NEWS +@@ -15,6 +15,8 @@ New in 2.02: + * GPT PReP. + * New `progress' module that shows progress information while reading + files. ++ * ZFS features support. ++ * ZFS LZ4 support. + + * New/improved terminal and video support: + * Monochrome text (matching `hercules' in GRUB Legacy). +@@ -36,6 +38,7 @@ New in 2.02: + * Enable `linux16' on all x86 platforms, not just BIOS. + * New TrueCrypt ISO loader. + * multiboot2 boot-services EFI specification. ++ * multiboot2 EFI memory map specification. + * multiboot2 full-file specfication. + + * New/improved network support: +@@ -51,12 +54,15 @@ New in 2.02: + * Ability to launch another payload from flash or disk + * Coreboot framebuffer + * CBMEMC support (both logging and inspecting logs) +- * Inspecting coreboot timestamps. +- * Inspecting coreboot tables. ++ * Command for inspecting coreboot timestamps (`coreboot_boottime'). ++ * Command for inspecting coreboot tables (`lscoreboot'). ++ * New target default_payload.elf. ++ * Increased maximal core size. + + * New/improved platform support: + * New `efifwsetup' and `lsefi' commands on EFI platforms. + * New `cmosdump' and `cmosset' commands on platforms with CMOS support. ++ * New command `pcidump' for PCI platforms. + * Improve opcode parsing in ACPI halt implementation. + * Use the TSC as a possible time source on i386-ieee1275. + * Merge PowerPC grub-mkrescue implementation with the common one. +@@ -77,6 +83,8 @@ New in 2.02: + * Support Yeeloong 3A. + * Add `cpuid --pae' option to detect Physical Address Extension on x86. + * Support for USB debug dongles. ++ * Support for *-emu on all platforms (previously only i386/x86_64 worked). ++ * Support *-emu on Windows. + + * Security: + * Add optional facility to enforce that all files read by the core image +@@ -88,6 +96,8 @@ New in 2.02: + * Initialise USB ports in parallel. + * New `testspeed' command to test file read speed. + * Speed-up gfxterm by storing intermediate results in more compact format. ++ * Lazy LVM/mdraid scan. ++ * Disk hints. + + * Scripting: + * New `eval' and `tr' commands. +@@ -105,7 +115,8 @@ New in 2.02: + * grub-install, grub-mknetdir, grub-mkrescue, and grub-mkstandalone + rewritten in C. They should now work in supported non-Unix-like + environments. +- * Native mingw support, including ability to install on EFI under windows. ++ * Native mingw support. ++ * Ability to install on EFI under windows. + * Reorganise timeout handling using new `timeout_style' environment + variable and `GRUB_TIMEOUT_STYLE' configuration key for grub-mkconfig. + Menu hotkeys pressed during a hidden timeout now boot the corresponding +@@ -122,6 +133,7 @@ New in 2.02: + * Partial mingw64 x86_64-efi compile support (highly experimental). + * Partial mingw32 i386-* (other than already present i386-pc) + compile support (highly experimental). ++ * Support for grub-mkpasswd on Windows. + * Eliminate the use of AutoGen. This allowed some performance + improvements to the build system. + * Remove variable length arrays. diff --git a/SOURCES/0020-grub-core-kern-efi-efi.c-Ensure-that-the-result-star.patch b/SOURCES/0020-grub-core-kern-efi-efi.c-Ensure-that-the-result-star.patch new file mode 100644 index 0000000..0c964a6 --- /dev/null +++ b/SOURCES/0020-grub-core-kern-efi-efi.c-Ensure-that-the-result-star.patch @@ -0,0 +1,85 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Sat, 18 Jan 2014 16:41:47 +0100 +Subject: [PATCH] * grub-core/kern/efi/efi.c: Ensure that the result starts + with / and has no //. + +--- + grub-core/kern/efi/efi.c | 25 +++++++++++++++++-------- + ChangeLog | 5 +++++ + 2 files changed, 22 insertions(+), 8 deletions(-) + +diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c +index b253141f26e..b9eb1ab1e33 100644 +--- a/grub-core/kern/efi/efi.c ++++ b/grub-core/kern/efi/efi.c +@@ -309,7 +309,7 @@ grub_efi_modules_addr (void) + char * + grub_efi_get_filename (grub_efi_device_path_t *dp0) + { +- char *name = 0, *p; ++ char *name = 0, *p, *pi; + grub_size_t filesize = 0; + grub_efi_device_path_t *dp; + +@@ -328,7 +328,7 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0) + grub_efi_uint16_t len; + len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4) + / sizeof (grub_efi_char16_t)); +- filesize += GRUB_MAX_UTF8_PER_UTF16 * len + 1; ++ filesize += GRUB_MAX_UTF8_PER_UTF16 * len + 2; + } + + dp = GRUB_EFI_NEXT_DEVICE_PATH (dp); +@@ -356,12 +356,12 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0) + grub_efi_file_path_device_path_t *fp; + grub_efi_uint16_t len; + +- if (p != name) +- *p++ = '/'; ++ *p++ = '/'; + + len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4) + / sizeof (grub_efi_char16_t)); + fp = (grub_efi_file_path_device_path_t *) dp; ++ + p = (char *) grub_utf16_to_utf8 ((unsigned char *) p, fp->path_name, len); + } + +@@ -370,10 +370,19 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0) + + *p = '\0'; + +- /* EFI breaks paths with backslashes. */ +- for (p = name; *p; p++) +- if (*p == '\\') +- *p = '/'; ++ for (pi = name, p = name; *pi;) ++ { ++ /* EFI breaks paths with backslashes. */ ++ if (*pi == '\\' || *pi == '/') ++ { ++ *p++ = '/'; ++ while (*pi == '\\' || *pi == '/') ++ pi++; ++ continue; ++ } ++ *p++ = *pi++; ++ } ++ *p = '\0'; + + return name; + } +diff --git a/ChangeLog b/ChangeLog +index 6a19f850448..b04a4ef70b9 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2014-01-18 Vladimir Serbinenko ++ ++ * grub-core/kern/efi/efi.c: Ensure that the result starts with / ++ and has no //. ++ + 2014-01-18 Vladimir Serbinenko + + * NEWS: Add few missing entries. diff --git a/SOURCES/0021-util-grub-mount.c-Extend-GCC-warning-workaround-to-g.patch b/SOURCES/0021-util-grub-mount.c-Extend-GCC-warning-workaround-to-g.patch new file mode 100644 index 0000000..c406ede --- /dev/null +++ b/SOURCES/0021-util-grub-mount.c-Extend-GCC-warning-workaround-to-g.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Sat, 18 Jan 2014 16:43:29 +0100 +Subject: [PATCH] * util/grub-mount.c: Extend GCC warning workaround to + grub-mount. + +--- + util/grub-mount.c | 7 ++++++- + ChangeLog | 4 ++++ + 2 files changed, 10 insertions(+), 1 deletion(-) + +diff --git a/util/grub-mount.c b/util/grub-mount.c +index 118881e0d9d..19de2e62057 100644 +--- a/util/grub-mount.c ++++ b/util/grub-mount.c +@@ -41,8 +41,13 @@ + #include + #include + ++#pragma GCC diagnostic ignored "-Wmissing-prototypes" ++#pragma GCC diagnostic ignored "-Wmissing-declarations" ++#include ++#pragma GCC diagnostic error "-Wmissing-prototypes" ++#pragma GCC diagnostic error "-Wmissing-declarations" ++ + #include "progname.h" +-#include "argp.h" + + static const char *root = NULL; + grub_device_t dev = NULL; +diff --git a/ChangeLog b/ChangeLog +index b04a4ef70b9..8534158b6c0 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2014-01-18 Vladimir Serbinenko ++ ++ * util/grub-mount.c: Extend GCC warning workaround to grub-mount. ++ + 2014-01-18 Vladimir Serbinenko + + * grub-core/kern/efi/efi.c: Ensure that the result starts with / diff --git a/SOURCES/0022-reintroduce-BUILD_LDFLAGS-for-the-cross-compile-case.patch b/SOURCES/0022-reintroduce-BUILD_LDFLAGS-for-the-cross-compile-case.patch new file mode 100644 index 0000000..aff34c5 --- /dev/null +++ b/SOURCES/0022-reintroduce-BUILD_LDFLAGS-for-the-cross-compile-case.patch @@ -0,0 +1,150 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrey Borzenkov +Date: Sat, 18 Jan 2014 19:50:54 +0400 +Subject: [PATCH] reintroduce BUILD_LDFLAGS for the cross-compile case + +This allows providing separate LDFLAGS for build and host environments, which +are not necessary the same for cross-compile case. In particular, it allows +building host programs statically to not depend on presence of libraries at +run-time (e.g. MinGW DLLs on Windows) while continue to use default dynamic +linking at build time. + +Also fix obsolete comments in confgure.ac - we do use different environment +for build and host now. +--- + configure.ac | 13 ++++++++----- + Makefile.am | 8 ++++---- + ChangeLog | 7 +++++++ + INSTALL | 3 ++- + grub-core/Makefile.am | 6 +++--- + 5 files changed, 24 insertions(+), 13 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 7c5d080b8a2..2e4cf3c2e22 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -26,11 +26,10 @@ dnl This is necessary because the target type in autoconf does not + dnl describe such a system very well. + dnl + dnl The current strategy is to use variables with no prefix (such as +-dnl CC, CFLAGS, etc.) for the host type as well as the build type, +-dnl because GRUB does not need to use those variables for the build +-dnl type, so there is no conflict. Variables with the prefix "TARGET_" +-dnl (such as TARGET_CC, TARGET_CFLAGS, etc.) are used for the target +-dnl type. ++dnl CC, CFLAGS, etc.) for the host type, variables with prefix "BUILD_" ++dnl (such as BUILD_CC, BUILD_CFLAGS, etc.) for the build type and variables ++dnl with the prefix "TARGET_" (such as TARGET_CC, TARGET_CFLAGS, etc.) are ++dnl used for the target type. See INSTALL for full list of variables. + + AC_INIT([GRUB],[2.02~beta2],[bug-grub@gnu.org]) + +@@ -477,6 +476,7 @@ AC_SUBST(HOST_CC) + AC_SUBST(BUILD_CC) + AC_SUBST(BUILD_CFLAGS) + AC_SUBST(BUILD_CPPFLAGS) ++AC_SUBST(BUILD_LDFLAGS) + AC_SUBST(TARGET_CC) + AC_SUBST(TARGET_NM) + AC_SUBST(TARGET_RANLIB) +@@ -1290,10 +1290,12 @@ SAVED_CC="$CC" + SAVED_CPP="$CPP" + SAVED_CFLAGS="$CFLAGS" + SAVED_CPPFLAGS="$CPPFLAGS" ++SAVED_LDFLAGS="$LDFLAGS" + CC="$BUILD_CC" + CPP="$BUILD_CPP" + CFLAGS="$BUILD_CFLAGS" + CPPFLAGS="$BUILD_CPPFLAGS" ++LDFLAGS="$BUILD_LDFAGS" + + unset ac_cv_c_bigendian + unset ac_cv_header_ft2build_h +@@ -1356,6 +1358,7 @@ CC="$SAVED_CC" + CPP="$SAVED_CPP" + CFLAGS="$SAVED_CFLAGS" + CPPFLAGS="$SAVED_CPPFLAGS" ++LDFLAGS="$SAVED_LDFLAGS" + + + DJVU_FONT_SOURCE= +diff --git a/Makefile.am b/Makefile.am +index 320e86f8f55..1bbec0e79d3 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -67,20 +67,20 @@ endif + starfield_theme_files = $(srcdir)/themes/starfield/blob_w.png $(srcdir)/themes/starfield/boot_menu_c.png $(srcdir)/themes/starfield/boot_menu_e.png $(srcdir)/themes/starfield/boot_menu_ne.png $(srcdir)/themes/starfield/boot_menu_n.png $(srcdir)/themes/starfield/boot_menu_nw.png $(srcdir)/themes/starfield/boot_menu_se.png $(srcdir)/themes/starfield/boot_menu_s.png $(srcdir)/themes/starfield/boot_menu_sw.png $(srcdir)/themes/starfield/boot_menu_w.png $(srcdir)/themes/starfield/slider_c.png $(srcdir)/themes/starfield/slider_n.png $(srcdir)/themes/starfield/slider_s.png $(srcdir)/themes/starfield/starfield.png $(srcdir)/themes/starfield/terminal_box_c.png $(srcdir)/themes/starfield/terminal_box_e.png $(srcdir)/themes/starfield/terminal_box_ne.png $(srcdir)/themes/starfield/terminal_box_n.png $(srcdir)/themes/starfield/terminal_box_nw.png $(srcdir)/themes/starfield/terminal_box_se.png $(srcdir)/themes/starfield/terminal_box_s.png $(srcdir)/themes/starfield/terminal_box_sw.png $(srcdir)/themes/starfield/terminal_box_w.png $(srcdir)/themes/starfield/theme.txt $(srcdir)/themes/starfield/README $(srcdir)/themes/starfield/COPYING.CC-BY-SA-3.0 + + build-grub-mkfont: util/grub-mkfont.c grub-core/unidata.c grub-core/kern/emu/misc.c util/misc.c +- $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-mkfont\" $^ $(build_freetype_cflags) $(build_freetype_libs) ++ $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-mkfont\" $^ $(build_freetype_cflags) $(build_freetype_libs) + CLEANFILES += build-grub-mkfont + + garbage-gen: util/garbage-gen.c +- $(BUILD_CC) -o $@ $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $^ ++ $(BUILD_CC) -o $@ $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) $^ + CLEANFILES += garbage-gen + EXTRA_DIST += util/garbage-gen.c + + build-grub-gen-asciih: util/grub-gen-asciih.c +- $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 $^ $(build_freetype_cflags) $(build_freetype_libs) -Wall -Werror ++ $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 $^ $(build_freetype_cflags) $(build_freetype_libs) -Wall -Werror + CLEANFILES += build-grub-gen-asciih + + build-grub-gen-widthspec: util/grub-gen-widthspec.c +- $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 $^ $(build_freetype_cflags) $(build_freetype_libs) -Wall -Werror ++ $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 $^ $(build_freetype_cflags) $(build_freetype_libs) -Wall -Werror + CLEANFILES += build-grub-gen-widthspec + + if COND_STARFIELD +diff --git a/ChangeLog b/ChangeLog +index 8534158b6c0..9c3ef2e2150 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,10 @@ ++2014-01-07 Andrey Borzenkov ++ ++ * configure.ac: Add support for BUILD_LDFLAGS. ++ * Makefile.am: Use BUILD_LDFLAGS for build time programs here ... ++ * grub-core/Makefile.am: ... and here. ++ * INSTALL: Mention BUILD_LDFLAGS. ++ + 2014-01-18 Vladimir Serbinenko + + * util/grub-mount.c: Extend GCC warning workaround to grub-mount. +diff --git a/INSTALL b/INSTALL +index db12530dff3..b67cd7f3476 100644 +--- a/INSTALL ++++ b/INSTALL +@@ -168,7 +168,8 @@ corresponding platform are not needed for the platform in question. + generate sin and cos tables. + 2. BUILD_CFLAGS= for C options for build. + 3. BUILD_CPPFLAGS= for C preprocessor options for build. +- 4. BUILD_FREETYPE= for freetype-config for build (optional). ++ 4. BUILD_LDFLAGS= for linker options for build. ++ 5. BUILD_FREETYPE= for freetype-config for build (optional). + + - For host + 1. --host= to autoconf name of host. +diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am +index 1b3142d2160..13b7979106f 100644 +--- a/grub-core/Makefile.am ++++ b/grub-core/Makefile.am +@@ -27,14 +27,14 @@ CPPFLAGS_LIBRARY += $(CPPFLAGS_PLATFORM) + CCASFLAGS_LIBRARY += $(CCASFLAGS_PLATFORM) + + build-grub-pep2elf: $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c +- $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) -DGRUB_BUILD=1 -DGRUB_TARGET_WORDSIZE=64 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pep2elf\" $^ ++ $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_BUILD=1 -DGRUB_TARGET_WORDSIZE=64 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pep2elf\" $^ + + build-grub-pe2elf: $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c +- $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) -DGRUB_BUILD=1 -DGRUB_TARGET_WORDSIZE=32 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pe2elf\" $^ ++ $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_BUILD=1 -DGRUB_TARGET_WORDSIZE=32 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pe2elf\" $^ + + # gentrigtables + gentrigtables: gentrigtables.c +- $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $< $(BUILD_LIBM) ++ $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) $< $(BUILD_LIBM) + CLEANFILES += gentrigtables + + # trigtables.c diff --git a/SOURCES/0023-grub-core-term-terminfo.c-Recognize-keys-F1-F12.patch b/SOURCES/0023-grub-core-term-terminfo.c-Recognize-keys-F1-F12.patch new file mode 100644 index 0000000..64ecaea --- /dev/null +++ b/SOURCES/0023-grub-core-term-terminfo.c-Recognize-keys-F1-F12.patch @@ -0,0 +1,151 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Sat, 18 Jan 2014 16:57:35 +0100 +Subject: [PATCH] * grub-core/term/terminfo.c: Recognize keys F1-F12. + +--- + grub-core/term/terminfo.c | 86 +++++++++++++++++++++++++++-------------------- + ChangeLog | 4 +++ + 2 files changed, 54 insertions(+), 36 deletions(-) + +diff --git a/grub-core/term/terminfo.c b/grub-core/term/terminfo.c +index 3d48b198fbd..f0d3e3debc6 100644 +--- a/grub-core/term/terminfo.c ++++ b/grub-core/term/terminfo.c +@@ -460,28 +460,31 @@ grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len, + {'@', GRUB_TERM_KEY_INSERT}, + }; + +- static struct +- { +- char key; +- unsigned ascii; +- } +- four_code_table[] = ++ static unsigned four_code_table[] = + { +- {'1', GRUB_TERM_KEY_HOME}, +- {'3', GRUB_TERM_KEY_DC}, +- {'5', GRUB_TERM_KEY_PPAGE}, +- {'6', GRUB_TERM_KEY_NPAGE}, +- {'7', GRUB_TERM_KEY_HOME}, +- {'8', GRUB_TERM_KEY_END} ++ [1] = GRUB_TERM_KEY_HOME, ++ [3] = GRUB_TERM_KEY_DC, ++ [5] = GRUB_TERM_KEY_PPAGE, ++ [6] = GRUB_TERM_KEY_NPAGE, ++ [7] = GRUB_TERM_KEY_HOME, ++ [8] = GRUB_TERM_KEY_END, ++ [17] = GRUB_TERM_KEY_F6, ++ [18] = GRUB_TERM_KEY_F7, ++ [19] = GRUB_TERM_KEY_F8, ++ [20] = GRUB_TERM_KEY_F9, ++ [21] = GRUB_TERM_KEY_F10, ++ [23] = GRUB_TERM_KEY_F11, ++ [24] = GRUB_TERM_KEY_F12, + }; + char fx_key[] = + { 'P', 'Q', 'w', 'x', 't', 'u', +- 'q', 'r', 'p', 'M', 'A', 'B' }; ++ 'q', 'r', 'p', 'M', 'A', 'B', 'H', 'F' }; + unsigned fx_code[] = + { GRUB_TERM_KEY_F1, GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3, + GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5, GRUB_TERM_KEY_F6, + GRUB_TERM_KEY_F7, GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9, +- GRUB_TERM_KEY_F10, GRUB_TERM_KEY_F11, GRUB_TERM_KEY_F12 }; ++ GRUB_TERM_KEY_F10, GRUB_TERM_KEY_F11, GRUB_TERM_KEY_F12, ++ GRUB_TERM_KEY_HOME, GRUB_TERM_KEY_END }; + unsigned i; + + if (c == '\e') +@@ -492,19 +495,13 @@ grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len, + { + CONTINUE_READ; + +- switch (c) +- { +- case 'H': +- keys[0] = GRUB_TERM_KEY_HOME; +- *len = 1; +- return; +- case 'F': +- keys[0] = GRUB_TERM_KEY_END; +- *len = 1; +- return; +- default: +- return; +- } ++ for (i = 0; i < ARRAY_SIZE (fx_key); i++) ++ if (fx_key[i] == c) ++ { ++ keys[0] = fx_code[i]; ++ *len = 1; ++ return; ++ } + } + + if (c != '[') +@@ -523,6 +520,15 @@ grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len, + + switch (c) + { ++ case '[': ++ CONTINUE_READ; ++ if (c >= 'A' && c <= 'E') ++ { ++ keys[0] = GRUB_TERM_KEY_F1 + c - 'A'; ++ *len = 1; ++ return; ++ } ++ return; + case 'O': + CONTINUE_READ; + for (i = 0; i < ARRAY_SIZE (fx_key); i++) +@@ -555,18 +561,26 @@ grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len, + return; + } + +- default: +- for (i = 0; i < ARRAY_SIZE (four_code_table); i++) +- if (four_code_table[i].key == c) ++ case '1' ... '9': ++ { ++ unsigned val = c - '0'; ++ CONTINUE_READ; ++ if (c >= '0' && c <= '9') + { ++ val = val * 10 + (c - '0'); + CONTINUE_READ; +- if (c != '~') +- return; +- keys[0] = four_code_table[i].ascii; +- *len = 1; +- return; + } +- return; ++ if (c != '~') ++ return; ++ if (val >= ARRAY_SIZE (four_code_table) ++ || four_code_table[val] == 0) ++ return; ++ keys[0] = four_code_table[val]; ++ *len = 1; ++ return; ++ } ++ default: ++ return; + } + } + #undef CONTINUE_READ +diff --git a/ChangeLog b/ChangeLog +index 9c3ef2e2150..bdfbf44da88 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2014-01-18 Vladimir Serbinenko ++ ++ * grub-core/term/terminfo.c: Recognize keys F1-F12. ++ + 2014-01-07 Andrey Borzenkov + + * configure.ac: Add support for BUILD_LDFLAGS. diff --git a/SOURCES/0024-Fix-ChangeLog-date.patch b/SOURCES/0024-Fix-ChangeLog-date.patch new file mode 100644 index 0000000..56dbb01 --- /dev/null +++ b/SOURCES/0024-Fix-ChangeLog-date.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrey Borzenkov +Date: Sat, 18 Jan 2014 20:01:16 +0400 +Subject: [PATCH] Fix ChangeLog date + +--- + ChangeLog | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ChangeLog b/ChangeLog +index bdfbf44da88..fcbf2207b32 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -2,7 +2,7 @@ + + * grub-core/term/terminfo.c: Recognize keys F1-F12. + +-2014-01-07 Andrey Borzenkov ++2014-01-18 Andrey Borzenkov + + * configure.ac: Add support for BUILD_LDFLAGS. + * Makefile.am: Use BUILD_LDFLAGS for build time programs here ... diff --git a/SOURCES/0025-Use-_W64-to-detect-MinGW-W64-32-instead-of-_FILE_OFF.patch b/SOURCES/0025-Use-_W64-to-detect-MinGW-W64-32-instead-of-_FILE_OFF.patch new file mode 100644 index 0000000..fdec621 --- /dev/null +++ b/SOURCES/0025-Use-_W64-to-detect-MinGW-W64-32-instead-of-_FILE_OFF.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrey Borzenkov +Date: Sat, 18 Jan 2014 20:04:11 +0400 +Subject: [PATCH] Use _W64 to detect MinGW W64-32 instead of _FILE_OFFSET_BITS + +In 94cee4a4c201bb506377b2c26e072eee8cb19d6f I overlooked that config.h +unconditionally sets _FILE_OFFSET_BITS, so it cannot be used to detect +MinGW W64 environment. It looks like Emacs folks already found +solution; instead of _FILE_OFFSET_BITS use _W64 as suggested in +http://lists.gnu.org/archive/html/emacs-devel/2013-03/msg00723.html +--- + include/grub/osdep/hostfile_windows.h | 4 ++-- + ChangeLog | 5 +++++ + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/include/grub/osdep/hostfile_windows.h b/include/grub/osdep/hostfile_windows.h +index 79efcfa5084..bf6451b6db4 100644 +--- a/include/grub/osdep/hostfile_windows.h ++++ b/include/grub/osdep/hostfile_windows.h +@@ -69,8 +69,8 @@ enum grub_util_fd_open_flags_t + + #if defined (__MINGW32__) && !defined (__MINGW64__) + +-/* 32 bit on MinGW-64 already redefines them if _FILE_OFFSET_BITS=64 */ +-#if !defined(_FILE_OFFSET_BITS) ++/* 32 bit on Mingw-w64 already redefines them if _FILE_OFFSET_BITS=64 */ ++#ifndef _W64 + #define fseeko fseeko64 + #define ftello ftello64 + #endif +diff --git a/ChangeLog b/ChangeLog +index fcbf2207b32..5aac7c1d854 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2014-01-18 Andrey Borzenkov ++ ++ * include/grub/osdep/hostfile_windows.h: Use _W64 instead of ++ FILE_OFFSET_BITS to differentiate between native MinGW and Mingw W64. ++ + 2014-01-18 Vladimir Serbinenko + + * grub-core/term/terminfo.c: Recognize keys F1-F12. diff --git a/SOURCES/0026-add-BUILD_EXEEXT-support-to-fix-make-clean-on-Window.patch b/SOURCES/0026-add-BUILD_EXEEXT-support-to-fix-make-clean-on-Window.patch new file mode 100644 index 0000000..63738d5 --- /dev/null +++ b/SOURCES/0026-add-BUILD_EXEEXT-support-to-fix-make-clean-on-Window.patch @@ -0,0 +1,169 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrey Borzenkov +Date: Sat, 18 Jan 2014 20:41:24 +0400 +Subject: [PATCH] add BUILD_EXEEXT support to fix make clean on Windows + +Add $(BUILD_EXEEXT) to ensure files are removed. Also add CLEANFILES where +appropriate. +--- + configure.ac | 21 ++++++++++++++++----- + Makefile.util.def | 2 +- + Makefile.am | 16 ++++++++-------- + ChangeLog | 7 +++++++ + grub-core/Makefile.am | 14 ++++++++------ + 5 files changed, 40 insertions(+), 20 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 2e4cf3c2e22..cf3de3be1fc 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -38,7 +38,8 @@ AC_CONFIG_AUX_DIR([build-aux]) + # We don't want -g -O2 by default in CFLAGS + : ${CFLAGS=""} + +-# Checks for host and target systems. ++# Checks for build, host and target systems. ++AC_CANONICAL_BUILD + AC_CANONICAL_HOST + save_program_prefix="${program_prefix}" + AC_CANONICAL_TARGET +@@ -422,6 +423,16 @@ case "$build_os" in + haiku*) BUILD_LIBM= ;; + *) BUILD_LIBM=-lm ;; + esac ++ ++dnl FIXME proper test seems to require too deep dive into Autoconf internals. ++dnl For now just list known platforms that we support. ++ ++case "$build_os" in ++ cygwin*|mingw32*|mingw64*) BUILD_EXEEXT=.exe ;; ++ *) BUILD_EXEEXT= ;; ++esac ++AC_SUBST(BUILD_EXEEXT) ++ + # For gnulib. + gl_INIT + +@@ -765,11 +776,11 @@ if test x"$platform" = xemu ; then + *windows* | *cygwin* | *mingw*) + if test x${target_cpu} = xi386 ; then + grub_cv_target_cc_link_format=-mi386pe; +- TARGET_OBJ2ELF='./build-grub-pe2elf'; ++ TARGET_OBJ2ELF='./build-grub-pe2elf$(BUILD_EXEEXT)'; + fi + if test x${target_cpu} = xx86_64 ; then + grub_cv_target_cc_link_format=-mi386pep; +- TARGET_OBJ2ELF='./build-grub-pep2elf'; ++ TARGET_OBJ2ELF='./build-grub-pep2elf$(BUILD_EXEEXT)'; + fi + TARGET_LDFLAGS="$TARGET_LDFLAGS -Wl,$grub_cv_target_cc_link_format" + ;; +@@ -803,10 +814,10 @@ elif test x"$target_cpu" = xi386 || test x"$target_cpu" = xx86_64; then + fi + TARGET_LDFLAGS="$TARGET_LDFLAGS -Wl,$grub_cv_target_cc_link_format" + if test x"$grub_cv_target_cc_link_format" = x-mi386pe ; then +- TARGET_OBJ2ELF='./build-grub-pe2elf'; ++ TARGET_OBJ2ELF='./build-grub-pe2elf$(BUILD_EXEEXT)'; + fi + if test x"$grub_cv_target_cc_link_format" = x-mi386pep ; then +- TARGET_OBJ2ELF='./build-grub-pep2elf'; ++ TARGET_OBJ2ELF='./build-grub-pep2elf$(BUILD_EXEEXT)'; + fi + fi + +diff --git a/Makefile.util.def b/Makefile.util.def +index 3c99be2b0ca..83df212f412 100644 +--- a/Makefile.util.def ++++ b/Makefile.util.def +@@ -708,7 +708,7 @@ script = { + name = grub-fs-tester; + common = tests/util/grub-fs-tester.in; + installdir = noinst; +- dependencies = garbage-gen; ++ dependencies = 'garbage-gen$(BUILD_EXEEXT)'; + }; + + script = { +diff --git a/Makefile.am b/Makefile.am +index 1bbec0e79d3..aa526f573c3 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -66,22 +66,22 @@ endif + + starfield_theme_files = $(srcdir)/themes/starfield/blob_w.png $(srcdir)/themes/starfield/boot_menu_c.png $(srcdir)/themes/starfield/boot_menu_e.png $(srcdir)/themes/starfield/boot_menu_ne.png $(srcdir)/themes/starfield/boot_menu_n.png $(srcdir)/themes/starfield/boot_menu_nw.png $(srcdir)/themes/starfield/boot_menu_se.png $(srcdir)/themes/starfield/boot_menu_s.png $(srcdir)/themes/starfield/boot_menu_sw.png $(srcdir)/themes/starfield/boot_menu_w.png $(srcdir)/themes/starfield/slider_c.png $(srcdir)/themes/starfield/slider_n.png $(srcdir)/themes/starfield/slider_s.png $(srcdir)/themes/starfield/starfield.png $(srcdir)/themes/starfield/terminal_box_c.png $(srcdir)/themes/starfield/terminal_box_e.png $(srcdir)/themes/starfield/terminal_box_ne.png $(srcdir)/themes/starfield/terminal_box_n.png $(srcdir)/themes/starfield/terminal_box_nw.png $(srcdir)/themes/starfield/terminal_box_se.png $(srcdir)/themes/starfield/terminal_box_s.png $(srcdir)/themes/starfield/terminal_box_sw.png $(srcdir)/themes/starfield/terminal_box_w.png $(srcdir)/themes/starfield/theme.txt $(srcdir)/themes/starfield/README $(srcdir)/themes/starfield/COPYING.CC-BY-SA-3.0 + +-build-grub-mkfont: util/grub-mkfont.c grub-core/unidata.c grub-core/kern/emu/misc.c util/misc.c ++build-grub-mkfont$(BUILD_EXEEXT): util/grub-mkfont.c grub-core/unidata.c grub-core/kern/emu/misc.c util/misc.c + $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-mkfont\" $^ $(build_freetype_cflags) $(build_freetype_libs) +-CLEANFILES += build-grub-mkfont ++CLEANFILES += build-grub-mkfont$(BUILD_EXEEXT) + +-garbage-gen: util/garbage-gen.c ++garbage-gen$(BUILD_EXEEXT): util/garbage-gen.c + $(BUILD_CC) -o $@ $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) $^ +-CLEANFILES += garbage-gen ++CLEANFILES += garbage-gen$(BUILD_EXEEXT) + EXTRA_DIST += util/garbage-gen.c + +-build-grub-gen-asciih: util/grub-gen-asciih.c ++build-grub-gen-asciih$(BUILD_EXEEXT): util/grub-gen-asciih.c + $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 $^ $(build_freetype_cflags) $(build_freetype_libs) -Wall -Werror +-CLEANFILES += build-grub-gen-asciih ++CLEANFILES += build-grub-gen-asciih$(BUILD_EXEEXT) + +-build-grub-gen-widthspec: util/grub-gen-widthspec.c ++build-grub-gen-widthspec$(BUILD_EXEEXT): util/grub-gen-widthspec.c + $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 $^ $(build_freetype_cflags) $(build_freetype_libs) -Wall -Werror +-CLEANFILES += build-grub-gen-widthspec ++CLEANFILES += build-grub-gen-widthspec$(BUILD_EXEEXT) + + if COND_STARFIELD + starfield_DATA = dejavu_10.pf2 dejavu_12.pf2 dejavu_bold_14.pf2 dejavu_14.pf2 dejavu_16.pf2 $(starfield_theme_files) +diff --git a/ChangeLog b/ChangeLog +index 5aac7c1d854..dad2da2faef 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,10 @@ ++2014-01-18 Andrey Borzenkov ++ ++ * configure.ac: Add support for BUILD_EXEEXT and use it ... ++ * Makefile.am: ... here. ++ * Makefile.util.def: ... and here. ++ * grub-core/Makefile.am: ... and here. ++ + 2014-01-18 Andrey Borzenkov + + * include/grub/osdep/hostfile_windows.h: Use _W64 instead of +diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am +index 13b7979106f..826b3dd7c1a 100644 +--- a/grub-core/Makefile.am ++++ b/grub-core/Makefile.am +@@ -26,20 +26,22 @@ CFLAGS_LIBRARY += $(CFLAGS_PLATFORM) -fno-builtin + CPPFLAGS_LIBRARY += $(CPPFLAGS_PLATFORM) + CCASFLAGS_LIBRARY += $(CCASFLAGS_PLATFORM) + +-build-grub-pep2elf: $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c ++build-grub-pep2elf$(BUILD_EXEEXT): $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c + $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_BUILD=1 -DGRUB_TARGET_WORDSIZE=64 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pep2elf\" $^ ++CLEANFILES += build-grub-pep2elf$(BUILD_EXEEXT) + +-build-grub-pe2elf: $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c ++build-grub-pe2elf$(BUILD_EXEEXT): $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c + $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_BUILD=1 -DGRUB_TARGET_WORDSIZE=32 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pe2elf\" $^ ++CLEANFILES += build-grub-pe2elf$(BUILD_EXEEXT) + + # gentrigtables +-gentrigtables: gentrigtables.c ++gentrigtables$(BUILD_EXEEXT): gentrigtables.c + $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) $< $(BUILD_LIBM) +-CLEANFILES += gentrigtables ++CLEANFILES += gentrigtables$(BUILD_EXEEXT) + + # trigtables.c +-trigtables.c: gentrigtables gentrigtables.c $(top_srcdir)/configure.ac +- ./gentrigtables > $@ ++trigtables.c: gentrigtables$(BUILD_EXEEXT) gentrigtables.c $(top_srcdir)/configure.ac ++ ./gentrigtables$(BUILD_EXEEXT) > $@ + CLEANFILES += trigtables.c + + # XXX Use Automake's LEX & YACC support diff --git a/SOURCES/0027-fix-include-loop-on-MinGW-due-to-libintl.h-pulling-s.patch b/SOURCES/0027-fix-include-loop-on-MinGW-due-to-libintl.h-pulling-s.patch new file mode 100644 index 0000000..796a9b9 --- /dev/null +++ b/SOURCES/0027-fix-include-loop-on-MinGW-due-to-libintl.h-pulling-s.patch @@ -0,0 +1,275 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrey Borzenkov +Date: Sat, 18 Jan 2014 21:22:57 +0400 +Subject: [PATCH] fix include loop on MinGW due to libintl.h pulling stdio.h + +In file included from ./include/grub/dl.h:23:0, + from grub-core/lib/libgcrypt-grub/cipher/rfc2268.c:3: +./include/grub/list.h:34:18: warning: conflicting types for 'grub_list_push' [en +abled by default] + void EXPORT_FUNC(grub_list_push) (grub_list_t *head, grub_list_t item); + ^ +./include/grub/symbol.h:68:25: note: in definition of macro 'EXPORT_FUNC' + # define EXPORT_FUNC(x) x + ^ +In file included from ./include/grub/fs.h:30:0, + from ./include/grub/file.h:25, + from ./grub-core/lib/posix_wrap/stdio.h:23, + from c:\mingw\include\libintl.h:314, + from ./include/grub/i18n.h:33, + from ./include/grub/misc.h:27, + from ./include/grub/list.h:25, + from ./include/grub/dl.h:28, + from grub-core/lib/libgcrypt-grub/cipher/rfc2268.c:3: +./include/grub/partition.h:106:3: note: previous implicit declaration of 'grub_l +ist_push' was here + grub_list_push (GRUB_AS_LIST_P (&grub_partition_map_list), + ^ +list.h needs just ATTRIBUTE_ERROR from misc.h; split compiler features +into separate file grub/compiler.h and include it instead. +--- + grub-core/commands/fileXX.c | 1 + + grub-core/efiemu/prepare.c | 1 + + grub-core/loader/i386/xen_file.c | 1 + + grub-core/loader/i386/xen_fileXX.c | 1 + + grub-core/video/capture.c | 1 + + include/grub/command.h | 1 + + include/grub/compiler.h | 51 ++++++++++++++++++++++++++++++++++++++ + include/grub/dl.h | 1 + + include/grub/list.h | 4 +-- + include/grub/misc.h | 29 +--------------------- + include/grub/procfs.h | 1 + + ChangeLog | 14 +++++++++++ + 12 files changed, 76 insertions(+), 30 deletions(-) + create mode 100644 include/grub/compiler.h + +diff --git a/grub-core/commands/fileXX.c b/grub-core/commands/fileXX.c +index c9857ff67b1..58e1094c68b 100644 +--- a/grub-core/commands/fileXX.c ++++ b/grub-core/commands/fileXX.c +@@ -18,6 +18,7 @@ + + #include + #include ++#include + + #pragma GCC diagnostic ignored "-Wcast-align" + +diff --git a/grub-core/efiemu/prepare.c b/grub-core/efiemu/prepare.c +index fb1b25d17f2..84c3368a82c 100644 +--- a/grub-core/efiemu/prepare.c ++++ b/grub-core/efiemu/prepare.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + #include + #include + +diff --git a/grub-core/loader/i386/xen_file.c b/grub-core/loader/i386/xen_file.c +index ebbf6aa11ba..ff23235f064 100644 +--- a/grub-core/loader/i386/xen_file.c ++++ b/grub-core/loader/i386/xen_file.c +@@ -18,6 +18,7 @@ + + #include + #include ++#include + + grub_elf_t + grub_xen_file (grub_file_t file) +diff --git a/grub-core/loader/i386/xen_fileXX.c b/grub-core/loader/i386/xen_fileXX.c +index 6df00157629..73a5f90fdb9 100644 +--- a/grub-core/loader/i386/xen_fileXX.c ++++ b/grub-core/loader/i386/xen_fileXX.c +@@ -17,6 +17,7 @@ + */ + + #include ++#include + + static grub_err_t + parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi, +diff --git a/grub-core/video/capture.c b/grub-core/video/capture.c +index 67c8edde824..4f83c744116 100644 +--- a/grub-core/video/capture.c ++++ b/grub-core/video/capture.c +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include + + static struct + { +diff --git a/include/grub/command.h b/include/grub/command.h +index 8705a635519..eee4e847ee4 100644 +--- a/include/grub/command.h ++++ b/include/grub/command.h +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + + typedef enum grub_command_flags + { +diff --git a/include/grub/compiler.h b/include/grub/compiler.h +new file mode 100644 +index 00000000000..c9e1d7a73dc +--- /dev/null ++++ b/include/grub/compiler.h +@@ -0,0 +1,51 @@ ++/* compiler.h - macros for various compiler features */ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2002,2003,2005,2006,2007,2008,2009,2010,2014 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_COMPILER_HEADER ++#define GRUB_COMPILER_HEADER 1 ++ ++/* GCC version checking borrowed from glibc. */ ++#if defined(__GNUC__) && defined(__GNUC_MINOR__) ++# define GNUC_PREREQ(maj,min) \ ++ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) ++#else ++# define GNUC_PREREQ(maj,min) 0 ++#endif ++ ++/* Does this compiler support compile-time error attributes? */ ++#if GNUC_PREREQ(4,3) ++# define ATTRIBUTE_ERROR(msg) \ ++ __attribute__ ((__error__ (msg))) ++#else ++# define ATTRIBUTE_ERROR(msg) __attribute__ ((noreturn)) ++#endif ++ ++#if GNUC_PREREQ(4,4) ++# define GNU_PRINTF gnu_printf ++#else ++# define GNU_PRINTF printf ++#endif ++ ++#if GNUC_PREREQ(3,4) ++# define WARN_UNUSED_RESULT __attribute__ ((warn_unused_result)) ++#else ++# define WARN_UNUSED_RESULT ++#endif ++ ++#endif /* ! GRUB_COMPILER_HEADER */ +diff --git a/include/grub/dl.h b/include/grub/dl.h +index d29a899f52c..9562fa6634c 100644 +--- a/include/grub/dl.h ++++ b/include/grub/dl.h +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #endif + + /* +diff --git a/include/grub/list.h b/include/grub/list.h +index edd20adfdb2..d170ff6da02 100644 +--- a/include/grub/list.h ++++ b/include/grub/list.h +@@ -21,8 +21,8 @@ + #define GRUB_LIST_HEADER 1 + + #include +-#include +-#include ++#include ++#include + + struct grub_list + { +diff --git a/include/grub/misc.h b/include/grub/misc.h +index 2cf74b55006..c6cd4564d86 100644 +--- a/include/grub/misc.h ++++ b/include/grub/misc.h +@@ -25,34 +25,7 @@ + #include + #include + #include +- +-/* GCC version checking borrowed from glibc. */ +-#if defined(__GNUC__) && defined(__GNUC_MINOR__) +-# define GNUC_PREREQ(maj,min) \ +- ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +-#else +-# define GNUC_PREREQ(maj,min) 0 +-#endif +- +-/* Does this compiler support compile-time error attributes? */ +-#if GNUC_PREREQ(4,3) +-# define ATTRIBUTE_ERROR(msg) \ +- __attribute__ ((__error__ (msg))) +-#else +-# define ATTRIBUTE_ERROR(msg) __attribute__ ((noreturn)) +-#endif +- +-#if GNUC_PREREQ(4,4) +-# define GNU_PRINTF gnu_printf +-#else +-# define GNU_PRINTF printf +-#endif +- +-#if GNUC_PREREQ(3,4) +-# define WARN_UNUSED_RESULT __attribute__ ((warn_unused_result)) +-#else +-# define WARN_UNUSED_RESULT +-#endif ++#include + + #define ALIGN_UP(addr, align) \ + ((addr + (typeof (addr)) align - 1) & ~((typeof (addr)) align - 1)) +diff --git a/include/grub/procfs.h b/include/grub/procfs.h +index d393da77f91..8cc331d946f 100644 +--- a/include/grub/procfs.h ++++ b/include/grub/procfs.h +@@ -20,6 +20,7 @@ + #define GRUB_PROCFS_HEADER 1 + + #include ++#include + + struct grub_procfs_entry + { +diff --git a/ChangeLog b/ChangeLog +index dad2da2faef..dad469b43b1 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,17 @@ ++2014-01-18 Andrey Borzenkov ++ ++ * include/grub/misc.h: Move macros for compiler features to ... ++ * include/grub/compiler.h: ... new file. ++ * include/grub/list.h: Include instead of . ++ * grub-core/commands/fileXX.c: Include . ++ * grub-core/efiemu/prepare.c: Include . ++ * grub-core/loader/i386/xen_file.c: Include . ++ * grub-core/loader/i386/xen_fileXX.c: Include . ++ * grub-core/video/capture.c: Include . ++ * include/grub/command.h: Include . ++ * include/grub/dl.h: Include . ++ * include/grub/procfs.h: Include . ++ + 2014-01-18 Andrey Borzenkov + + * configure.ac: Add support for BUILD_EXEEXT and use it ... diff --git a/SOURCES/0028-grub-core-commands-macbless.c-Rename-FILE-and-DIR-to.patch b/SOURCES/0028-grub-core-commands-macbless.c-Rename-FILE-and-DIR-to.patch new file mode 100644 index 0000000..88122a7 --- /dev/null +++ b/SOURCES/0028-grub-core-commands-macbless.c-Rename-FILE-and-DIR-to.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Sat, 18 Jan 2014 19:26:40 +0100 +Subject: [PATCH] * grub-core/commands/macbless.c: Rename FILE and DIR to avoid + conflicts. + + Reported by: Andrey Borzenkov. +--- + grub-core/commands/macbless.c | 6 +++--- + ChangeLog | 7 +++++++ + 2 files changed, 10 insertions(+), 3 deletions(-) + +diff --git a/grub-core/commands/macbless.c b/grub-core/commands/macbless.c +index c5210833ed0..4724edd7709 100644 +--- a/grub-core/commands/macbless.c ++++ b/grub-core/commands/macbless.c +@@ -37,7 +37,7 @@ struct find_node_context + grub_uint64_t inode_found; + char *dirname; + enum +- { NONE, FILE, DIR } found; ++ { FOUND_NONE, FOUND_FILE, FOUND_DIR } found; + }; + + static int +@@ -53,7 +53,7 @@ find_inode (const char *filename, + && grub_strcasecmp (ctx->dirname, filename) == 0))) + { + ctx->inode_found = info->inode; +- ctx->found = info->dir ? DIR : FILE; ++ ctx->found = info->dir ? FOUND_DIR : FOUND_FILE; + } + return 0; + } +@@ -175,7 +175,7 @@ grub_mac_bless_file (grub_device_t dev, const char *path_in, int intel) + grub_free (path); + + return grub_mac_bless_inode (dev, (grub_uint32_t) ctx.inode_found, +- (ctx.found == DIR), intel); ++ (ctx.found == FOUND_DIR), intel); + } + + static grub_err_t +diff --git a/ChangeLog b/ChangeLog +index dad469b43b1..9d1a3f051c1 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,10 @@ ++2014-01-18 Vladimir Serbinenko ++ ++ * grub-core/commands/macbless.c: Rename FILE and DIR to avoid ++ conflicts. ++ ++ Reported by: Andrey Borzenkov. ++ + 2014-01-18 Andrey Borzenkov + + * include/grub/misc.h: Move macros for compiler features to ... diff --git a/SOURCES/0029-Makefile.util.def-Link-grub-ofpathname-with-zfs-libs.patch b/SOURCES/0029-Makefile.util.def-Link-grub-ofpathname-with-zfs-libs.patch new file mode 100644 index 0000000..4bf38f3 --- /dev/null +++ b/SOURCES/0029-Makefile.util.def-Link-grub-ofpathname-with-zfs-libs.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mike Gilbert +Date: Sat, 18 Jan 2014 19:41:15 +0100 +Subject: [PATCH] * Makefile.util.def: Link grub-ofpathname with zfs libs. + +--- + Makefile.util.def | 2 +- + ChangeLog | 4 ++++ + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/Makefile.util.def b/Makefile.util.def +index 83df212f412..a286a89cd8d 100644 +--- a/Makefile.util.def ++++ b/Makefile.util.def +@@ -384,7 +384,7 @@ program = { + ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; +- ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBGEOM)'; ++ ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; + }; + + program = { +diff --git a/ChangeLog b/ChangeLog +index 9d1a3f051c1..edceb66dbcc 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2014-01-01 Mike Gilbert ++ ++ * Makefile.util.def: Link grub-ofpathname with zfs libs. ++ + 2014-01-18 Vladimir Serbinenko + + * grub-core/commands/macbless.c: Rename FILE and DIR to avoid diff --git a/SOURCES/0030-Makefile.am-default_payload.elf-Add-modules-multiboo.patch b/SOURCES/0030-Makefile.am-default_payload.elf-Add-modules-multiboo.patch new file mode 100644 index 0000000..b5781c4 --- /dev/null +++ b/SOURCES/0030-Makefile.am-default_payload.elf-Add-modules-multiboo.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Sat, 18 Jan 2014 19:43:19 +0100 +Subject: [PATCH] * Makefile.am (default_payload.elf): Add modules multiboot + cbmemc linux16 gzio echo help. + +--- + Makefile.am | 2 +- + ChangeLog | 7 ++++++- + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index aa526f573c3..97c062d7d35 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -399,7 +399,7 @@ bootcheck: $(BOOTCHECKS) + + if COND_i386_coreboot + default_payload.elf: grub-mkstandalone grub-mkimage +- pkgdatadir=. ./grub-mkstandalone --grub-mkimage=./grub-mkimage -O i386-coreboot -o $@ --modules='ahci pata ehci uhci ohci usb_keyboard usbms part_msdos xfs ext2 fat at_keyboard part_gpt usbserial_usbdebug cbfs' --install-modules='ls linux search configfile normal cbtime cbls memrw iorw minicmd lsmmap lspci halt reboot hexdump pcidump regexp setpci lsacpi chain test serial' --fonts= --themes= --locales= -d grub-core/ /boot/grub/grub.cfg=$(srcdir)/coreboot.cfg ++ pkgdatadir=. ./grub-mkstandalone --grub-mkimage=./grub-mkimage -O i386-coreboot -o $@ --modules='ahci pata ehci uhci ohci usb_keyboard usbms part_msdos xfs ext2 fat at_keyboard part_gpt usbserial_usbdebug cbfs' --install-modules='ls linux search configfile normal cbtime cbls memrw iorw minicmd lsmmap lspci halt reboot hexdump pcidump regexp setpci lsacpi chain test serial multiboot cbmemc linux16 gzio echo help' --fonts= --themes= --locales= -d grub-core/ /boot/grub/grub.cfg=$(srcdir)/coreboot.cfg + endif + + windowsdir=$(top_builddir)/$(PACKAGE)-$(VERSION)-for-windows +diff --git a/ChangeLog b/ChangeLog +index edceb66dbcc..cff9386d3d2 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,4 +1,9 @@ +-2014-01-01 Mike Gilbert ++2014-01-18 Vladimir Serbinenko ++ ++ * Makefile.am (default_payload.elf): Add modules ++ multiboot cbmemc linux16 gzio echo help. ++ ++2014-01-18 Mike Gilbert + + * Makefile.util.def: Link grub-ofpathname with zfs libs. + diff --git a/SOURCES/0031-fix-removal-of-cpu-machine-links-on-mingw-msys.patch b/SOURCES/0031-fix-removal-of-cpu-machine-links-on-mingw-msys.patch new file mode 100644 index 0000000..ae23226 --- /dev/null +++ b/SOURCES/0031-fix-removal-of-cpu-machine-links-on-mingw-msys.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrey Borzenkov +Date: Sat, 18 Jan 2014 22:48:04 +0400 +Subject: [PATCH] fix removal of {cpu,machine} links on mingw/msys + +At least on Windows 2003 using "ln -s dir1 dir2" in msys shell succeeds, +but results in what looks like hard link. Subsequent "rm -f dir2" (e.g. +during second config.status invocation) fails. Check that we also can +remove link to directory. + +Make it more clear in message that we are checking "ln -s". +--- + ChangeLog | 5 +++++ + acinclude.m4 | 6 +++--- + 2 files changed, 8 insertions(+), 3 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index cff9386d3d2..c3bfa9fcb1b 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2014-01-18 Andrey Borzenkov ++ ++ * acinclude.m4 (grub_CHECK_LINK_DIR): Check that we can also remove ++ symbolic link to directory. It fails in Msys shell on Windows 2003. ++ + 2014-01-18 Vladimir Serbinenko + + * Makefile.am (default_payload.elf): Add modules +diff --git a/acinclude.m4 b/acinclude.m4 +index 32d5477d100..b2bb88d838e 100644 +--- a/acinclude.m4 ++++ b/acinclude.m4 +@@ -418,15 +418,15 @@ else + [fi] + ]) + +-dnl Check if ln can handle directories properly (mingw). ++dnl Check if ln -s can handle directories properly (mingw). + AC_DEFUN([grub_CHECK_LINK_DIR],[ +-AC_MSG_CHECKING([whether ln can handle directories properly]) ++AC_MSG_CHECKING([whether ln -s can handle directories properly]) + [mkdir testdir 2>/dev/null + case $srcdir in + [\\/$]* | ?:[\\/]* ) reldir=$srcdir/include/grub/util ;; + *) reldir=../$srcdir/include/grub/util ;; + esac +-if ln -s $reldir testdir/util 2>/dev/null ; then] ++if ln -s $reldir testdir/util 2>/dev/null && rm -f testdir/util 2>/dev/null ; then] + AC_MSG_RESULT([yes]) + [link_dir=yes + else diff --git a/SOURCES/0032-grub-core-normal-main.c-read_config_file-Buffer-conf.patch b/SOURCES/0032-grub-core-normal-main.c-read_config_file-Buffer-conf.patch new file mode 100644 index 0000000..c019a8e --- /dev/null +++ b/SOURCES/0032-grub-core-normal-main.c-read_config_file-Buffer-conf.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Sat, 18 Jan 2014 19:54:09 +0100 +Subject: [PATCH] * grub-core/normal/main.c (read_config_file): Buffer config + file. Reduces boot time. + +--- + grub-core/normal/main.c | 14 +++++++++++--- + ChangeLog | 5 +++++ + 2 files changed, 16 insertions(+), 3 deletions(-) + +diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c +index c36663f738c..3a926fc5fa9 100644 +--- a/grub-core/normal/main.c ++++ b/grub-core/normal/main.c +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -104,7 +105,7 @@ read_config_file_getline (char **line, int cont __attribute__ ((unused)), + static grub_menu_t + read_config_file (const char *config) + { +- grub_file_t file; ++ grub_file_t rawfile, file; + char *old_file = 0, *old_dir = 0; + char *config_dir, *ptr = 0; + const char *ctmp; +@@ -122,10 +123,17 @@ read_config_file (const char *config) + } + + /* Try to open the config file. */ +- file = grub_file_open (config); +- if (! file) ++ rawfile = grub_file_open (config); ++ if (! rawfile) + return 0; + ++ file = grub_bufio_open (rawfile, 0); ++ if (! file) ++ { ++ grub_file_close (file); ++ return 0; ++ } ++ + ctmp = grub_env_get ("config_file"); + if (ctmp) + old_file = grub_strdup (ctmp); +diff --git a/ChangeLog b/ChangeLog +index c3bfa9fcb1b..c84f7e7cc00 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2014-01-18 Vladimir Serbinenko ++ ++ * grub-core/normal/main.c (read_config_file): Buffer config file. ++ Reduces boot time. ++ + 2014-01-18 Andrey Borzenkov + + * acinclude.m4 (grub_CHECK_LINK_DIR): Check that we can also remove diff --git a/SOURCES/0033-util-grub-install.c-Fix-a-typo.patch b/SOURCES/0033-util-grub-install.c-Fix-a-typo.patch new file mode 100644 index 0000000..f4eb803 --- /dev/null +++ b/SOURCES/0033-util-grub-install.c-Fix-a-typo.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Sat, 18 Jan 2014 20:02:51 +0100 +Subject: [PATCH] * util/grub-install.c: Fix a typo. + +--- + util/grub-install.c | 2 +- + ChangeLog | 4 ++++ + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/util/grub-install.c b/util/grub-install.c +index 4608b80fe05..5903f340a61 100644 +--- a/util/grub-install.c ++++ b/util/grub-install.c +@@ -1259,7 +1259,7 @@ main (int argc, char *argv[]) + + if (!config.is_cryptodisk_enabled && have_cryptodisk) + grub_util_error (_("attempt to install to encrypted disk without cryptodisk enabled. " +- "Set `%s' in file `%s'."), "GRUB_ENABLE_CRYPTODISK=1", ++ "Set `%s' in file `%s'."), "GRUB_ENABLE_CRYPTODISK=y", + grub_util_get_config_filename ()); + + if (disk_module && grub_strcmp (disk_module, "ata") == 0) +diff --git a/ChangeLog b/ChangeLog +index c84f7e7cc00..9360345efc2 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2014-01-18 Vladimir Serbinenko ++ ++ * util/grub-install.c: Fix a typo. ++ + 2014-01-18 Vladimir Serbinenko + + * grub-core/normal/main.c (read_config_file): Buffer config file. diff --git a/SOURCES/0034-use-MODULE_FILES-for-genemuinit-instead-of-MOD_FILES.patch b/SOURCES/0034-use-MODULE_FILES-for-genemuinit-instead-of-MOD_FILES.patch new file mode 100644 index 0000000..b4fd228 --- /dev/null +++ b/SOURCES/0034-use-MODULE_FILES-for-genemuinit-instead-of-MOD_FILES.patch @@ -0,0 +1,88 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrey Borzenkov +Date: Sat, 18 Jan 2014 23:15:40 +0400 +Subject: [PATCH] use MODULE_FILES for genemuinit* instead of MOD_FILES + +MinGW native nm does not support ELF binaries. +--- + ChangeLog | 8 ++++++++ + grub-core/Makefile.am | 8 ++++---- + grub-core/genemuinit.sh | 4 ++-- + grub-core/genemuinitheader.sh | 4 ++-- + 4 files changed, 16 insertions(+), 8 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index 9360345efc2..4688ff4e6d3 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,11 @@ ++2014-01-18 Andrey Borzenkov ++ ++ * grub-core/Makefile.am: Build grub_emu_init.[ch] from MODULE_FILES ++ instead of MOD_FILES. ++ * grub-core/genemuinit.sh: Simplify stripping of suffix so it works ++ both with and without .exe. ++ * grub-core/genemuinitheader.sh: Same. ++ + 2014-01-18 Vladimir Serbinenko + + * util/grub-install.c: Fix a typo. +diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am +index 826b3dd7c1a..5c087c83b8f 100644 +--- a/grub-core/Makefile.am ++++ b/grub-core/Makefile.am +@@ -294,12 +294,12 @@ grub_emu-grub_emu_init.$(OBJEXT):grub_emu_init.h + kern/emu/grub_emu_dyn-main.$(OBJEXT):grub_emu_init.h + grub_emu_dyn-grub_emu_init.$(OBJEXT):grub_emu_init.h + +-grub_emu_init.h: genemuinitheader.sh $(MOD_FILES) +- rm -f $@; echo $(MOD_FILES) | sh $(srcdir)/genemuinitheader.sh $(TARGET_NM) > $@ ++grub_emu_init.h: genemuinitheader.sh $(MODULE_FILES) ++ rm -f $@; echo $(MODULE_FILES) | sh $(srcdir)/genemuinitheader.sh $(TARGET_NM) > $@ + CLEANFILES += grub_emu_init.h + +-grub_emu_init.c: grub_emu_init.h genemuinit.sh $(MOD_FILES) +- rm -f $@; echo $(MOD_FILES) | sh $(srcdir)/genemuinit.sh $(TARGET_NM) > $@ ++grub_emu_init.c: grub_emu_init.h genemuinit.sh $(MODULE_FILES) ++ rm -f $@; echo $(MODULE_FILES) | sh $(srcdir)/genemuinit.sh $(TARGET_NM) > $@ + CLEANFILES += grub_emu_init.c + endif + +diff --git a/grub-core/genemuinit.sh b/grub-core/genemuinit.sh +index 45c15ecb9f4..8c6bb1c18ff 100644 +--- a/grub-core/genemuinit.sh ++++ b/grub-core/genemuinit.sh +@@ -47,7 +47,7 @@ EOF + read mods + for line in $mods; do + if ${nm} --defined-only -P -p ${line} | grep grub_mod_init > /dev/null; then +- echo "grub_${line}_init ();" | sed 's,\.mod,,g;' ++ echo "grub_${line%%.*}_init ();" + fi + done + +@@ -63,7 +63,7 @@ EOF + + for line in $mods; do + if ${nm} --defined-only -P -p ${line} | grep grub_mod_fini > /dev/null; then +- echo "grub_${line}_fini ();" | sed 's,\.mod,,g;' ++ echo "grub_${line%%.*}_fini ();" + fi + done + +diff --git a/grub-core/genemuinitheader.sh b/grub-core/genemuinitheader.sh +index 6b83f599317..a99a15d06f1 100644 +--- a/grub-core/genemuinitheader.sh ++++ b/grub-core/genemuinitheader.sh +@@ -44,9 +44,9 @@ EOF + read mods + for line in $mods; do + if ${nm} --defined-only -P -p ${line} | grep grub_mod_init > /dev/null; then +- echo "void grub_${line}_init (void);" | sed 's,\.mod,,g;' ++ echo "void grub_${line%%.*}_init (void);" + fi + if ${nm} --defined-only -P -p ${line} | grep grub_mod_fini > /dev/null; then +- echo "void grub_${line}_fini (void);" | sed 's,\.mod,,g;' ++ echo "void grub_${line%%.*}_fini (void);" + fi + done diff --git a/SOURCES/0035-Ignore-EPERM-when-modifying-kern.geom.debugflags.patch b/SOURCES/0035-Ignore-EPERM-when-modifying-kern.geom.debugflags.patch new file mode 100644 index 0000000..0c2043c --- /dev/null +++ b/SOURCES/0035-Ignore-EPERM-when-modifying-kern.geom.debugflags.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Colin Watson +Date: Fri, 17 Jan 2014 02:28:46 +0000 +Subject: [PATCH] Ignore EPERM when modifying kern.geom.debugflags + +Many tests fail when run as a non-root user on FreeBSD. The failures +all amount to an inability to open files using grub_util_fd_open, +because we cannot set the kern.geom.debugflags sysctl. This sysctl is +indeed important to allow us to do such things as installing GRUB to the +MBR, but if we need to do that and can't then we will get an error +later. Enforcing it here is unnecessary and prevents otherwise +perfectly reasonable operations. +--- + grub-core/osdep/freebsd/hostdisk.c | 12 ++++++++++-- + ChangeLog | 7 +++++++ + 2 files changed, 17 insertions(+), 2 deletions(-) + +diff --git a/grub-core/osdep/freebsd/hostdisk.c b/grub-core/osdep/freebsd/hostdisk.c +index eb202dcc831..6145d073555 100644 +--- a/grub-core/osdep/freebsd/hostdisk.c ++++ b/grub-core/osdep/freebsd/hostdisk.c +@@ -102,8 +102,16 @@ grub_util_fd_open (const char *os_dev, int flags) + if (! (sysctl_oldflags & 0x10) + && sysctlbyname ("kern.geom.debugflags", NULL , 0, &sysctl_flags, sysctl_size)) + { +- grub_error (GRUB_ERR_BAD_DEVICE, "cannot set flags of sysctl kern.geom.debugflags"); +- return GRUB_UTIL_FD_INVALID; ++ if (errno == EPERM) ++ /* Running as an unprivileged user; don't worry about restoring ++ flags, although if we try to write to anything interesting such ++ as the MBR then we may fail later. */ ++ sysctl_oldflags = 0x10; ++ else ++ { ++ grub_error (GRUB_ERR_BAD_DEVICE, "cannot set flags of sysctl kern.geom.debugflags"); ++ return GRUB_UTIL_FD_INVALID; ++ } + } + + ret = open (os_dev, flags, S_IROTH | S_IRGRP | S_IRUSR | S_IWUSR); +diff --git a/ChangeLog b/ChangeLog +index 4688ff4e6d3..10abfe28f20 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,10 @@ ++2014-01-19 Colin Watson ++ ++ * grub-core/osdep/freebsd/hostdisk.c (grub_util_fd_open): Ignore ++ EPERM when modifying kern.geom.debugflags. It is only a problem for ++ such things as installing GRUB to the MBR, in which case there'll be ++ an error later anyway, not for opening files during tests. ++ + 2014-01-18 Andrey Borzenkov + + * grub-core/Makefile.am: Build grub_emu_init.[ch] from MODULE_FILES diff --git a/SOURCES/0036-change-stop-condition-to-avoid-infinite-loops.patch b/SOURCES/0036-change-stop-condition-to-avoid-infinite-loops.patch new file mode 100644 index 0000000..e16c2d1 --- /dev/null +++ b/SOURCES/0036-change-stop-condition-to-avoid-infinite-loops.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paulo Flabiano Smorigo +Date: Tue, 21 Jan 2014 10:49:39 -0200 +Subject: [PATCH] change stop condition to avoid infinite loops + +In net/net.c there is a while (1) that only exits if there is a stop +condition and more then 10 packages or if there is no package received. + +If GRUB is idle and enter in this loop, the only condition to leave is +if it doesn't have incoming packages. In a network with heavy traffic +this never happens. +--- + grub-core/net/net.c | 2 +- + ChangeLog | 12 ++++++++++++ + 2 files changed, 13 insertions(+), 1 deletion(-) + +diff --git a/grub-core/net/net.c b/grub-core/net/net.c +index 0e57e93e821..56355f3c98c 100644 +--- a/grub-core/net/net.c ++++ b/grub-core/net/net.c +@@ -1453,7 +1453,7 @@ receive_packets (struct grub_net_card *card, int *stop_condition) + } + card->opened = 1; + } +- while (1) ++ while (received < 100) + { + /* Maybe should be better have a fixed number of packets for each card + and just mark them as used and not used. */ +diff --git a/ChangeLog b/ChangeLog +index 10abfe28f20..f69d8c7e042 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,15 @@ ++2014-01-21 Paulo Flabiano Smorigo ++ ++ * grub-core/net/net.c (receive_packets): Change stop condition to avoid ++ infinite loops. ++ ++ In net/net.c there is a while (1) that only exits if there is a stop ++ condition and more then 10 packages or if there is no package received. ++ ++ If GRUB is idle and enter in this loop, the only condition to leave is ++ if it doesn't have incoming packages. In a network with heavy traffic ++ this never happens. ++ + 2014-01-19 Colin Watson + + * grub-core/osdep/freebsd/hostdisk.c (grub_util_fd_open): Ignore diff --git a/SOURCES/0037-increase-network-try-interval-gradually.patch b/SOURCES/0037-increase-network-try-interval-gradually.patch new file mode 100644 index 0000000..f3ddc4c --- /dev/null +++ b/SOURCES/0037-increase-network-try-interval-gradually.patch @@ -0,0 +1,106 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paulo Flabiano Smorigo +Date: Tue, 21 Jan 2014 11:03:51 -0200 +Subject: [PATCH] increase network try interval gradually + +* grub-core/net/arp.c (grub_net_arp_send_request): Increase network try +interval gradually. +* grub-core/net/icmp6.c (grub_net_icmp6_send_request): Likewise. +* grub-core/net/net.c (grub_net_fs_read_real): Likewise. +* grub-core/net/tftp.c (tftp_open): Likewise. +* include/grub/net.h (GRUB_NET_INTERVAL_ADDITION): New define. +--- + grub-core/net/arp.c | 3 ++- + grub-core/net/icmp6.c | 3 ++- + grub-core/net/net.c | 5 +++-- + grub-core/net/tftp.c | 3 ++- + include/grub/net.h | 1 + + ChangeLog | 9 +++++++++ + 6 files changed, 19 insertions(+), 5 deletions(-) + +diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c +index e92c7e7daec..d62d0cc1e01 100644 +--- a/grub-core/net/arp.c ++++ b/grub-core/net/arp.c +@@ -110,7 +110,8 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf, + return GRUB_ERR_NONE; + pending_req = proto_addr->ipv4; + have_pending = 0; +- grub_net_poll_cards (GRUB_NET_INTERVAL, &have_pending); ++ grub_net_poll_cards (GRUB_NET_INTERVAL + (i * GRUB_NET_INTERVAL_ADDITION), ++ &have_pending); + if (grub_net_link_layer_resolve_check (inf, proto_addr)) + return GRUB_ERR_NONE; + nb.data = nbd; +diff --git a/grub-core/net/icmp6.c b/grub-core/net/icmp6.c +index 2741e6f11fb..bbc902014fe 100644 +--- a/grub-core/net/icmp6.c ++++ b/grub-core/net/icmp6.c +@@ -518,7 +518,8 @@ grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf, + { + if (grub_net_link_layer_resolve_check (inf, proto_addr)) + break; +- grub_net_poll_cards (GRUB_NET_INTERVAL, 0); ++ grub_net_poll_cards (GRUB_NET_INTERVAL + (i * GRUB_NET_INTERVAL_ADDITION), ++ 0); + if (grub_net_link_layer_resolve_check (inf, proto_addr)) + break; + nb->data = nbd; +diff --git a/grub-core/net/net.c b/grub-core/net/net.c +index 56355f3c98c..1521d8d2c87 100644 +--- a/grub-core/net/net.c ++++ b/grub-core/net/net.c +@@ -1558,8 +1558,9 @@ grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len) + if (!net->eof) + { + try++; +- grub_net_poll_cards (GRUB_NET_INTERVAL, &net->stall); +- } ++ grub_net_poll_cards (GRUB_NET_INTERVAL + ++ (try * GRUB_NET_INTERVAL_ADDITION), &net->stall); ++ } + else + return total; + } +diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c +index 9c489f1fc94..51736142764 100644 +--- a/grub-core/net/tftp.c ++++ b/grub-core/net/tftp.c +@@ -398,7 +398,8 @@ tftp_open (struct grub_file *file, const char *filename) + destroy_pq (data); + return err; + } +- grub_net_poll_cards (GRUB_NET_INTERVAL, &data->have_oack); ++ grub_net_poll_cards (GRUB_NET_INTERVAL + (i * GRUB_NET_INTERVAL_ADDITION), ++ &data->have_oack); + if (data->have_oack) + break; + } +diff --git a/include/grub/net.h b/include/grub/net.h +index de6259ee1a0..0e0a605c5a6 100644 +--- a/include/grub/net.h ++++ b/include/grub/net.h +@@ -532,5 +532,6 @@ extern char *grub_net_default_server; + + #define GRUB_NET_TRIES 40 + #define GRUB_NET_INTERVAL 400 ++#define GRUB_NET_INTERVAL_ADDITION 20 + + #endif /* ! GRUB_NET_HEADER */ +diff --git a/ChangeLog b/ChangeLog +index f69d8c7e042..f5618a6eb70 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,12 @@ ++2014-01-21 Paulo Flabiano Smorigo ++ ++ * grub-core/net/arp.c (grub_net_arp_send_request): Increase network try ++ interval gradually. ++ * grub-core/net/icmp6.c (grub_net_icmp6_send_request): Likewise. ++ * grub-core/net/net.c (grub_net_fs_read_real): Likewise. ++ * grub-core/net/tftp.c (tftp_open): Likewise. ++ * include/grub/net.h (GRUB_NET_INTERVAL_ADDITION): New define. ++ + 2014-01-21 Paulo Flabiano Smorigo + + * grub-core/net/net.c (receive_packets): Change stop condition to avoid diff --git a/SOURCES/0038-look-for-DejaVu-also-in-usr-share-fonts-truetype.patch b/SOURCES/0038-look-for-DejaVu-also-in-usr-share-fonts-truetype.patch new file mode 100644 index 0000000..72a51a0 --- /dev/null +++ b/SOURCES/0038-look-for-DejaVu-also-in-usr-share-fonts-truetype.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrey Borzenkov +Date: Tue, 21 Jan 2014 19:29:33 +0400 +Subject: [PATCH] look for DejaVu also in /usr/share/fonts/truetype + +It is installed in this path on openSUSE. +--- + configure.ac | 2 +- + ChangeLog | 4 ++++ + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index cf3de3be1fc..120263e9c58 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1389,7 +1389,7 @@ fi + + if test x"$starfield_excuse" = x; then + for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz; do +- for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/truetype/ttf-dejavu /usr/share/fonts/dejavu; do ++ for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/truetype/ttf-dejavu /usr/share/fonts/dejavu /usr/share/fonts/truetype; do + if test -f "$dir/DejaVuSans.$ext"; then + DJVU_FONT_SOURCE="$dir/DejaVuSans.$ext" + break 2 +diff --git a/ChangeLog b/ChangeLog +index f5618a6eb70..9f5d81dfbac 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2014-01-21 Andrey Borzenkov ++ ++ * configure.ac: Look for DejaVuSans also in /usr/share/fonts/truetype. ++ + 2014-01-21 Paulo Flabiano Smorigo + + * grub-core/net/arp.c (grub_net_arp_send_request): Increase network try diff --git a/SOURCES/0039-Show-detected-path-to-DejaVuSans-in-configure-summar.patch b/SOURCES/0039-Show-detected-path-to-DejaVuSans-in-configure-summar.patch new file mode 100644 index 0000000..9162ce2 --- /dev/null +++ b/SOURCES/0039-Show-detected-path-to-DejaVuSans-in-configure-summar.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrey Borzenkov +Date: Tue, 21 Jan 2014 19:41:11 +0400 +Subject: [PATCH] Show detected path to DejaVuSans in configure summary + +--- + configure.ac | 1 + + ChangeLog | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/configure.ac b/configure.ac +index 120263e9c58..8888c2ff29c 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1816,6 +1816,7 @@ echo grub-mount: No "($grub_mount_excuse)" + fi + if [ x"$starfield_excuse" = x ]; then + echo starfield theme: Yes ++echo With DejaVuSans font from $DJVU_FONT_SOURCE + else + echo starfield theme: No "($starfield_excuse)" + fi +diff --git a/ChangeLog b/ChangeLog +index 9f5d81dfbac..3ba57aed842 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,6 +1,7 @@ + 2014-01-21 Andrey Borzenkov + + * configure.ac: Look for DejaVuSans also in /usr/share/fonts/truetype. ++ Show detected font path in summary. + + 2014-01-21 Paulo Flabiano Smorigo + diff --git a/SOURCES/0040-add-GRUB_WINDOWS_EXTRA_DIST-to-allow-shipping-runtim.patch b/SOURCES/0040-add-GRUB_WINDOWS_EXTRA_DIST-to-allow-shipping-runtim.patch new file mode 100644 index 0000000..832f2f1 --- /dev/null +++ b/SOURCES/0040-add-GRUB_WINDOWS_EXTRA_DIST-to-allow-shipping-runtim.patch @@ -0,0 +1,56 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrey Borzenkov +Date: Tue, 21 Jan 2014 20:54:09 +0400 +Subject: [PATCH] add GRUB_WINDOWS_EXTRA_DIST to allow shipping runtime files + +Not all toolkits provide static libraries. This patch enables creation of self +contained distribution that does not require pre-existing runtime libraries. +Intended usage is + +export GRUB_WINDOWS_EXTRA_DIST="/path/to/liblzma.dll /path/to/libintl.dll" +make +make windowszip + +As those libraries and locations are dependent on toolchain in use, trying +to autodetect them is likely impossible. So just provide a simple way to +package everything in one step. + +Also remove $(windowsdir) after ZIP was created same as other "make dist" +targets. +--- + Makefile.am | 4 ++++ + ChangeLog | 5 +++++ + 2 files changed, 9 insertions(+) + +diff --git a/Makefile.am b/Makefile.am +index 97c062d7d35..f02ae0a393c 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -420,10 +420,14 @@ windowsdir: $(PROGRAMS) $(starfield_DATA) $(platform_DATA) + for x in $(starfield_DATA); do \ + cp -fp $$x $(windowsdir)/themes/starfield/$$(basename $$x); \ + done ++ for x in $(GRUB_WINDOWS_EXTRA_DIST); do \ ++ cp -fp $$x $(windowsdir); \ ++ done + + windowszip=$(top_builddir)/$(PACKAGE)-$(VERSION)-for-windows.zip + windowszip: windowsdir + test -f $(windowszip) && rm $(windowszip) || true + zip -r $(windowszip) $(windowsdir) ++ rm -rf $(windowsdir) + + EXTRA_DIST += linguas.sh +diff --git a/ChangeLog b/ChangeLog +index 3ba57aed842..1ede3709165 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2014-01-21 Andrey Borzenkov ++ ++ * Makefile.am: Allow adding extra files to generated Windows ZIP ++ archive by setting GRUB_WINDOWS_EXTRA_DIST. ++ + 2014-01-21 Andrey Borzenkov + + * configure.ac: Look for DejaVuSans also in /usr/share/fonts/truetype. diff --git a/SOURCES/0041-util-grub-install.c-write_to_disk-Add-an-info-messag.patch b/SOURCES/0041-util-grub-install.c-write_to_disk-Add-an-info-messag.patch new file mode 100644 index 0000000..003b15f --- /dev/null +++ b/SOURCES/0041-util-grub-install.c-write_to_disk-Add-an-info-messag.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Colin Watson +Date: Thu, 23 Jan 2014 12:05:36 +0000 +Subject: [PATCH] * util/grub-install.c (write_to_disk): Add an info message. + +--- + util/grub-install.c | 1 + + ChangeLog | 4 ++++ + 2 files changed, 5 insertions(+) + +diff --git a/util/grub-install.c b/util/grub-install.c +index 5903f340a61..787dc90fce5 100644 +--- a/util/grub-install.c ++++ b/util/grub-install.c +@@ -675,6 +675,7 @@ write_to_disk (grub_device_t dev, const char *fn) + + core_img = grub_util_read_image (fn); + ++ grub_util_info ("writing `%s' to `%s'", fn, dev->disk->name); + err = grub_disk_write (dev->disk, 0, 0, + core_size, core_img); + free (core_img); +diff --git a/ChangeLog b/ChangeLog +index 1ede3709165..eee8e78a726 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2014-01-23 Colin Watson ++ ++ * util/grub-install.c (write_to_disk): Add an info message. ++ + 2014-01-21 Andrey Borzenkov + + * Makefile.am: Allow adding extra files to generated Windows ZIP diff --git a/SOURCES/0042-util-grub-install.c-List-available-targets.patch b/SOURCES/0042-util-grub-install.c-List-available-targets.patch new file mode 100644 index 0000000..364f5af --- /dev/null +++ b/SOURCES/0042-util-grub-install.c-List-available-targets.patch @@ -0,0 +1,106 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Fri, 24 Jan 2014 18:09:25 +0100 +Subject: [PATCH] * util/grub-install.c: List available targets. + +--- + util/grub-install-common.c | 30 ++++++++++++++++++++++++++++++ + util/grub-install.c | 10 ++++++++-- + include/grub/util/install.h | 2 ++ + ChangeLog | 4 ++++ + 4 files changed, 44 insertions(+), 2 deletions(-) + +diff --git a/util/grub-install-common.c b/util/grub-install-common.c +index 6ea0a8e1795..c8bedcb2e59 100644 +--- a/util/grub-install-common.c ++++ b/util/grub-install-common.c +@@ -667,6 +667,36 @@ static struct + [GRUB_INSTALL_PLATFORM_ARM_UBOOT] = { "arm", "uboot" }, + }; + ++char * ++grub_install_get_platforms_string (void) ++{ ++ char **arr = xmalloc (sizeof (char *) * ARRAY_SIZE (platforms)); ++ int platform_strins_len = 0; ++ char *platforms_string; ++ char *ptr; ++ unsigned i; ++ for (i = 0; i < ARRAY_SIZE (platforms); i++) ++ { ++ arr[i] = xasprintf ("%s-%s", platforms[i].cpu, ++ platforms[i].platform); ++ platform_strins_len += strlen (arr[i]) + 2; ++ } ++ ptr = platforms_string = xmalloc (platform_strins_len); ++ qsort (arr, ARRAY_SIZE (platforms), sizeof (char *), grub_qsort_strcmp); ++ for (i = 0; i < ARRAY_SIZE (platforms); i++) ++ { ++ strcpy (ptr, arr[i]); ++ ptr += strlen (arr[i]); ++ *ptr++ = ','; ++ *ptr++ = ' '; ++ free (arr[i]); ++ } ++ ptr[-2] = 0; ++ free (arr); ++ ++ return platforms_string; ++} ++ + char * + grub_install_get_platform_name (enum grub_install_plat platid) + { +diff --git a/util/grub-install.c b/util/grub-install.c +index 787dc90fce5..2e6226a3716 100644 +--- a/util/grub-install.c ++++ b/util/grub-install.c +@@ -256,7 +256,7 @@ static struct argp_option options[] = { + OPTION_HIDDEN, 0, 2}, + {"target", OPTION_TARGET, N_("TARGET"), + /* TRANSLATORS: "TARGET" as in "target platform". */ +- 0, N_("install GRUB for TARGET platform [default=%s]"), 2}, ++ 0, N_("install GRUB for TARGET platform [default=%s]; available targets: %s"), 2}, + {"grub-setup", OPTION_SETUP, "FILE", OPTION_HIDDEN, 0, 2}, + {"grub-mkrelpath", OPTION_MKRELPATH, "FILE", OPTION_HIDDEN, 0, 2}, + {"grub-mkdevicemap", OPTION_MKDEVICEMAP, "FILE", OPTION_HIDDEN, 0, 2}, +@@ -340,7 +340,13 @@ help_filter (int key, const char *text, void *input __attribute__ ((unused))) + case OPTION_BOOT_DIRECTORY: + return xasprintf (text, GRUB_DIR_NAME, GRUB_BOOT_DIR_NAME "/" GRUB_DIR_NAME); + case OPTION_TARGET: +- return xasprintf (text, get_default_platform ()); ++ { ++ char *plats = grub_install_get_platforms_string (); ++ char *ret; ++ ret = xasprintf (text, get_default_platform (), plats); ++ free (plats); ++ return ret; ++ } + case ARGP_KEY_HELP_POST_DOC: + return xasprintf (text, program_name, GRUB_BOOT_DIR_NAME "/" GRUB_DIR_NAME); + default: +diff --git a/include/grub/util/install.h b/include/grub/util/install.h +index bc987aadc16..aedcd29f905 100644 +--- a/include/grub/util/install.h ++++ b/include/grub/util/install.h +@@ -138,6 +138,8 @@ grub_install_get_platform_cpu (enum grub_install_plat platid); + const char * + grub_install_get_platform_platform (enum grub_install_plat platid); + ++char * ++grub_install_get_platforms_string (void); + + typedef enum { + GRUB_COMPRESSION_AUTO, +diff --git a/ChangeLog b/ChangeLog +index eee8e78a726..20e8baaa23e 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2014-01-24 Vladimir Serbinenko ++ ++ * util/grub-install.c: List available targets. ++ + 2014-01-23 Colin Watson + + * util/grub-install.c (write_to_disk): Add an info message. diff --git a/SOURCES/0043-Fix-several-translatable-strings.patch b/SOURCES/0043-Fix-several-translatable-strings.patch new file mode 100644 index 0000000..7cbc73f --- /dev/null +++ b/SOURCES/0043-Fix-several-translatable-strings.patch @@ -0,0 +1,73 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Fri, 24 Jan 2014 18:20:27 +0100 +Subject: [PATCH] Fix several translatable strings. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + + Suggested by: D. Prévot. +--- + grub-core/commands/syslinuxcfg.c | 2 +- + grub-core/loader/arm64/linux.c | 2 +- + util/grub-syslinux2cfg.c | 4 ++-- + ChangeLog | 6 ++++++ + 4 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/grub-core/commands/syslinuxcfg.c b/grub-core/commands/syslinuxcfg.c +index a4bfc40b6d2..00ae113c5a7 100644 +--- a/grub-core/commands/syslinuxcfg.c ++++ b/grub-core/commands/syslinuxcfg.c +@@ -50,7 +50,7 @@ static const struct grub_arg_option options[] = + N_("root directory of the syslinux disk [default=/]."), + N_("DIR"), ARG_TYPE_STRING}, + {"cwd", 'c', 0, +- N_("current directory of the syslinux [default is parent directory of input file]."), ++ N_("current directory of syslinux [default is parent directory of input file]."), + N_("DIR"), ARG_TYPE_STRING}, + {"isolinux", 'i', 0, N_("assume input is an isolinux configuration file."), 0, 0}, + {"pxelinux", 'p', 0, N_("assume input is a pxelinux configuration file."), 0, 0}, +diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c +index 75ad871a81c..65129c21a8d 100644 +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -120,7 +120,7 @@ check_kernel (struct grub_arm64_linux_kernel_header *lh) + + if ((lh->code0 & 0xffff) != GRUB_EFI_PE_MAGIC) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, +- N_("plain Image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled")); ++ N_("plain image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled")); + + grub_dprintf ("linux", "UEFI stub kernel:\n"); + grub_dprintf ("linux", "text_offset = 0x%012llx\n", +diff --git a/util/grub-syslinux2cfg.c b/util/grub-syslinux2cfg.c +index 5e944c20a83..f4fda6db9bb 100644 +--- a/util/grub-syslinux2cfg.c ++++ b/util/grub-syslinux2cfg.c +@@ -66,10 +66,10 @@ static struct argp_option options[] = { + N_("root directory of the syslinux disk [default=/]."), 0}, + {"target-cwd", 'T', N_("DIR"), 0, + N_( +- "current directory of the syslinux as it will be seen on runtime [default is parent directory of input file]." ++ "current directory of syslinux as it will be seen on runtime [default is parent directory of input file]." + ), 0}, + {"cwd", 'c', N_("DIR"), 0, +- N_("current directory of the syslinux [default is parent directory of input file]."), 0}, ++ N_("current directory of syslinux [default is parent directory of input file]."), 0}, + + {"output", 'o', N_("FILE"), 0, N_("write output to FILE [default=stdout]."), 0}, + {"isolinux", 'i', 0, 0, N_("assume input is an isolinux configuration file."), 0}, +diff --git a/ChangeLog b/ChangeLog +index 20e8baaa23e..e149d8ef33d 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,9 @@ ++2014-01-24 Vladimir Serbinenko ++ ++ Fix several translatable strings. ++ ++ Suggested by: D. Prévot. ++ + 2014-01-24 Vladimir Serbinenko + + * util/grub-install.c: List available targets. diff --git a/SOURCES/0044-do-not-set-default-prefix-in-grub-mkimage.patch b/SOURCES/0044-do-not-set-default-prefix-in-grub-mkimage.patch new file mode 100644 index 0000000..3a6d430 --- /dev/null +++ b/SOURCES/0044-do-not-set-default-prefix-in-grub-mkimage.patch @@ -0,0 +1,72 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrey Borzenkov +Date: Sat, 25 Jan 2014 19:54:51 +0400 +Subject: [PATCH] do not set default prefix in grub-mkimage + +Default prefix is likely wrong on Unix and completely wrong on Windows. +Let caller set it explicitly to avoid any ambiguity. +--- + util/grub-mkimage.c | 16 +++++++++++----- + ChangeLog | 4 ++++ + 2 files changed, 15 insertions(+), 5 deletions(-) + +diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c +index a2bd4c196e5..1e0bcf1bf4f 100644 +--- a/util/grub-mkimage.c ++++ b/util/grub-mkimage.c +@@ -64,7 +64,7 @@ static struct argp_option options[] = { + {"directory", 'd', N_("DIR"), 0, + /* TRANSLATORS: platform here isn't identifier. It can be translated. */ + N_("use images and modules under DIR [default=%s/]"), 0}, +- {"prefix", 'p', N_("DIR"), 0, N_("set prefix directory [default=%s]"), 0}, ++ {"prefix", 'p', N_("DIR"), 0, N_("set prefix directory"), 0}, + {"memdisk", 'm', N_("FILE"), 0, + /* TRANSLATORS: "memdisk" here isn't an identifier, it can be translated. + "embed" is a verb (command description). "*/ +@@ -93,8 +93,6 @@ help_filter (int key, const char *text, void *input __attribute__ ((unused))) + { + case 'd': + return xasprintf (text, grub_util_get_pkglibdir ()); +- case 'p': +- return xasprintf (text, DEFAULT_DIRECTORY); + case 'O': + { + char *formats = grub_install_get_image_targets_string (), *ret; +@@ -268,6 +266,15 @@ main (int argc, char *argv[]) + exit(1); + } + ++ if (!arguments.prefix) ++ { ++ char *program = xstrdup(program_name); ++ printf ("%s\n", _("Prefix not specified (use the -p option).")); ++ argp_help (&argp, stderr, ARGP_HELP_STD_USAGE, program); ++ free (program); ++ exit(1); ++ } ++ + if (arguments.output) + { + fp = grub_util_fopen (arguments.output, "wb"); +@@ -287,8 +294,7 @@ main (int argc, char *argv[]) + strcpy (ptr, dn); + } + +- grub_install_generate_image (arguments.dir, +- arguments.prefix ? : DEFAULT_DIRECTORY, fp, ++ grub_install_generate_image (arguments.dir, arguments.prefix, fp, + arguments.output, arguments.modules, + arguments.memdisk, arguments.pubkeys, + arguments.npubkeys, arguments.config, +diff --git a/ChangeLog b/ChangeLog +index e149d8ef33d..b405b7ee5bd 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2014-01-25 Andrey Borzenkov ++ ++ * util/grub-mkimage.c: Make prefix argument mandatory. ++ + 2014-01-24 Vladimir Serbinenko + + Fix several translatable strings. diff --git a/SOURCES/0045-fix-Mingw-W64-32-cross-compile-failure-due-to-printf.patch b/SOURCES/0045-fix-Mingw-W64-32-cross-compile-failure-due-to-printf.patch new file mode 100644 index 0000000..cbd9868 --- /dev/null +++ b/SOURCES/0045-fix-Mingw-W64-32-cross-compile-failure-due-to-printf.patch @@ -0,0 +1,105 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrey Borzenkov +Date: Sat, 25 Jan 2014 21:49:41 +0400 +Subject: [PATCH] fix Mingw W64-32 cross compile failure due to printf + redefinition in libintl.h + +In file included from util/misc.c:36:0: +./include/grub/emu/misc.h:56:1: error: 'libintl_printf' is an unrecognized format function type [-Werror=format=] + char * EXPORT_FUNC(xasprintf) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))) WARN_UNUSED_RESULT; + ^ +./include/grub/emu/misc.h:58:1: error: 'libintl_printf' is an unrecognized format function type [-Werror=format=] + +The reason is libintl.h which redefines printf as libintl_printf. The problem +is not present in native MinGW build which avoids redefinition. Use +(format (__printf__) instead which is valid replacement in GCC. + +v2: add grub-core/lib/libgcrypt/src/g10lib.h +v3: modify g10lib.h during import +--- + include/grub/crypto.h | 2 +- + include/grub/emu/misc.h | 8 ++++---- + include/grub/err.h | 2 +- + ChangeLog | 9 +++++++++ + util/import_gcry.py | 6 ++++++ + 5 files changed, 21 insertions(+), 6 deletions(-) + +diff --git a/include/grub/crypto.h b/include/grub/crypto.h +index ec1b980d2ec..a24e89dd9cd 100644 +--- a/include/grub/crypto.h ++++ b/include/grub/crypto.h +@@ -408,7 +408,7 @@ void _gcry_assert_failed (const char *expr, const char *file, int line, + const char *func) __attribute__ ((noreturn)); + + void _gcry_burn_stack (int bytes); +-void _gcry_log_error( const char *fmt, ... ) __attribute__ ((format (printf, 1, 2))); ++void _gcry_log_error( const char *fmt, ... ) __attribute__ ((format (__printf__, 1, 2))); + + + #ifdef GRUB_UTIL +diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h +index dde48c192d3..a588ba21da2 100644 +--- a/include/grub/emu/misc.h ++++ b/include/grub/emu/misc.h +@@ -53,11 +53,11 @@ grub_util_device_is_mapped (const char *dev); + void * EXPORT_FUNC(xmalloc) (grub_size_t size) WARN_UNUSED_RESULT; + void * EXPORT_FUNC(xrealloc) (void *ptr, grub_size_t size) WARN_UNUSED_RESULT; + char * EXPORT_FUNC(xstrdup) (const char *str) WARN_UNUSED_RESULT; +-char * EXPORT_FUNC(xasprintf) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))) WARN_UNUSED_RESULT; ++char * EXPORT_FUNC(xasprintf) (const char *fmt, ...) __attribute__ ((format (__printf__, 1, 2))) WARN_UNUSED_RESULT; + +-void EXPORT_FUNC(grub_util_warn) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); +-void EXPORT_FUNC(grub_util_info) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); +-void EXPORT_FUNC(grub_util_error) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2), noreturn)); ++void EXPORT_FUNC(grub_util_warn) (const char *fmt, ...) __attribute__ ((format (__printf__, 1, 2))); ++void EXPORT_FUNC(grub_util_info) (const char *fmt, ...) __attribute__ ((format (__printf__, 1, 2))); ++void EXPORT_FUNC(grub_util_error) (const char *fmt, ...) __attribute__ ((format (__printf__, 1, 2), noreturn)); + + grub_uint64_t EXPORT_FUNC (grub_util_get_cpu_time_ms) (void); + +diff --git a/include/grub/err.h b/include/grub/err.h +index 9896fccf98a..1590c688e1d 100644 +--- a/include/grub/err.h ++++ b/include/grub/err.h +@@ -91,6 +91,6 @@ int EXPORT_FUNC(grub_error_pop) (void); + void EXPORT_FUNC(grub_print_error) (void); + extern int EXPORT_VAR(grub_err_printed_errors); + int grub_err_printf (const char *fmt, ...) +- __attribute__ ((format (printf, 1, 2))); ++ __attribute__ ((format (__printf__, 1, 2))); + + #endif /* ! GRUB_ERR_HEADER */ +diff --git a/ChangeLog b/ChangeLog +index b405b7ee5bd..c93f11fbb20 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,12 @@ ++ ++2014-01-25 Andrey Borzenkov ++ ++ * include/grub/crypto.h: Replace __attribute__ ((format (printf)) with ++ __attribute__ ((format (__printf__)) to fix compilation under MinGW-w64. ++ * include/grub/emu/misc.h: ... and here. ++ * include/grub/err.h: ... and here. ++ * util/import_gcry.py: ... and here (in files g10lib.h). ++ + 2014-01-25 Andrey Borzenkov + + * util/grub-mkimage.c: Make prefix argument mandatory. +diff --git a/util/import_gcry.py b/util/import_gcry.py +index 63ebb90f1fe..2b3322d3a12 100644 +--- a/util/import_gcry.py ++++ b/util/import_gcry.py +@@ -534,6 +534,12 @@ for src in sorted (os.listdir (os.path.join (indir, "src"))): + fw.close () + continue + ++ if src == "g10lib.h": ++ fw.write (f.read ().replace ("(printf,f,a)", "(__printf__,f,a)")) ++ f.close () ++ fw.close () ++ continue ++ + fw.write (f.read ()) + f.close () + fw.close () diff --git a/SOURCES/0046-grub-core-term-serial.c-grub_serial_register-Fix-inv.patch b/SOURCES/0046-grub-core-term-serial.c-grub_serial_register-Fix-inv.patch new file mode 100644 index 0000000..2f0d133 --- /dev/null +++ b/SOURCES/0046-grub-core-term-serial.c-grub_serial_register-Fix-inv.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Sun, 26 Jan 2014 02:36:05 +0100 +Subject: [PATCH] * grub-core/term/serial.c (grub_serial_register): Fix invalid + free. Ensure that pointers are inited to NULL and that pointers are not + accessed after free. + +--- + grub-core/term/serial.c | 8 ++++---- + ChangeLog | 5 +++++ + 2 files changed, 9 insertions(+), 4 deletions(-) + +diff --git a/grub-core/term/serial.c b/grub-core/term/serial.c +index b581a763ed0..c9b5574ae3c 100644 +--- a/grub-core/term/serial.c ++++ b/grub-core/term/serial.c +@@ -338,23 +338,23 @@ grub_serial_register (struct grub_serial_port *port) + grub_free (indata); + return grub_errno; + } +- +- out = grub_malloc (sizeof (*out)); ++ ++ out = grub_zalloc (sizeof (*out)); + if (!out) + { +- grub_free (in); + grub_free (indata); + grub_free ((char *) in->name); ++ grub_free (in); + return grub_errno; + } + + outdata = grub_malloc (sizeof (*outdata)); + if (!outdata) + { +- grub_free (in); + grub_free (indata); + grub_free ((char *) in->name); + grub_free (out); ++ grub_free (in); + return grub_errno; + } + +diff --git a/ChangeLog b/ChangeLog +index c93f11fbb20..67b4d5c2add 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2014-01-26 Vladimir Serbinenko ++ ++ * grub-core/term/serial.c (grub_serial_register): Fix invalid free. ++ Ensure that pointers are inited to NULL and that pointers are not ++ accessed after free. + + 2014-01-25 Andrey Borzenkov + diff --git a/SOURCES/0047-grub-install-support-for-partitioned-partx-loop-devi.patch b/SOURCES/0047-grub-install-support-for-partitioned-partx-loop-devi.patch new file mode 100644 index 0000000..76f1a8e --- /dev/null +++ b/SOURCES/0047-grub-install-support-for-partitioned-partx-loop-devi.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mike Gilbert +Date: Sun, 26 Jan 2014 02:56:04 +0100 +Subject: [PATCH] grub-install: support for partitioned partx loop devices. + + * grub-core/osdep/linux/getroot.c (grub_util_part_to_disk): Detect + /dev/loopX as being the parent of /dev/loopXpY. +--- + grub-core/osdep/linux/getroot.c | 13 +++++++++++++ + ChangeLog | 7 +++++++ + 2 files changed, 20 insertions(+) + +diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c +index 772de0a9bc4..19581d32997 100644 +--- a/grub-core/osdep/linux/getroot.c ++++ b/grub-core/osdep/linux/getroot.c +@@ -883,6 +883,19 @@ grub_util_part_to_disk (const char *os_dev, struct stat *st, + *pp = '\0'; + return path; + } ++ ++ /* If this is a loop device */ ++ if ((strncmp ("loop", p, 4) == 0) && p[4] >= '0' && p[4] <= '9') ++ { ++ char *pp = p + 4; ++ while (*pp >= '0' && *pp <= '9') ++ pp++; ++ if (*pp == 'p') ++ *is_part = 1; ++ /* /dev/loop[0-9]+p[0-9]* */ ++ *pp = '\0'; ++ return path; ++ } + } + + return path; +diff --git a/ChangeLog b/ChangeLog +index 67b4d5c2add..bbec1e70bbd 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,10 @@ ++2014-01-26 Mike Gilbert ++ ++ grub-install: support for partitioned partx loop devices. ++ ++ * grub-core/osdep/linux/getroot.c (grub_util_part_to_disk): Detect ++ /dev/loopX as being the parent of /dev/loopXpY. ++ + 2014-01-26 Vladimir Serbinenko + + * grub-core/term/serial.c (grub_serial_register): Fix invalid free. diff --git a/SOURCES/0048-grub-core-term-at_keyboard.c-Tolerate-missing-keyboa.patch b/SOURCES/0048-grub-core-term-at_keyboard.c-Tolerate-missing-keyboa.patch new file mode 100644 index 0000000..cf332c0 --- /dev/null +++ b/SOURCES/0048-grub-core-term-at_keyboard.c-Tolerate-missing-keyboa.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Sun, 26 Jan 2014 03:31:10 +0100 +Subject: [PATCH] * grub-core/term/at_keyboard.c: Tolerate missing keyboard. + +--- + grub-core/term/at_keyboard.c | 3 +++ + ChangeLog | 4 ++++ + 2 files changed, 7 insertions(+) + +diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c +index f5071ce69e8..b4257e84a04 100644 +--- a/grub-core/term/at_keyboard.c ++++ b/grub-core/term/at_keyboard.c +@@ -396,6 +396,9 @@ fetch_key (int *is_break) + if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS))) + return -1; + at_key = grub_inb (KEYBOARD_REG_DATA); ++ /* May happen if no keyboard is connected. Just ignore this. */ ++ if (at_key == 0xff) ++ return -1; + if (at_key == 0xe0) + { + e0_received = 1; +diff --git a/ChangeLog b/ChangeLog +index bbec1e70bbd..d37d4a6fc16 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2014-01-26 Vladimir Serbinenko ++ ++ * grub-core/term/at_keyboard.c: Tolerate missing keyboard. ++ + 2014-01-26 Mike Gilbert + + grub-install: support for partitioned partx loop devices. diff --git a/SOURCES/0049-.gitignore-add-missing-files-and-.exe-variants.patch b/SOURCES/0049-.gitignore-add-missing-files-and-.exe-variants.patch new file mode 100644 index 0000000..267ab1e --- /dev/null +++ b/SOURCES/0049-.gitignore-add-missing-files-and-.exe-variants.patch @@ -0,0 +1,70 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paulo Flabiano Smorigo +Date: Wed, 29 Jan 2014 13:26:00 -0200 +Subject: [PATCH] .gitignore: add missing files and .exe variants. + +--- + .gitignore | 7 +++++++ + ChangeLog | 6 +++++- + 2 files changed, 12 insertions(+), 1 deletion(-) + +diff --git a/.gitignore b/.gitignore +index 2b0156acd7c..18ab8e81278 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -58,6 +58,8 @@ grub-emu.exe + grub-emu-lite.exe + grub_emu_init.c + grub_emu_init.h ++/grub-file ++/grub-file.exe + grub-fstest + grub-fstest.exe + grub_fstest_init.c +@@ -66,6 +68,8 @@ grub_func_test + grub-install + grub-install.exe + grub-kbdcomp ++/grub-macbless ++/grub-macbless.exe + grub-macho2img + /grub-menulst2cfg + /grub-menulst2cfg.exe +@@ -120,6 +124,8 @@ grub-shell + grub-shell-tester + grub-sparc64-setup + grub-sparc64-setup.exe ++/grub-syslinux2cfg ++/grub-syslinux2cfg.exe + gzcompress_test + hddboot_test + help_test +@@ -194,6 +200,7 @@ grub-core/modinfo.sh + grub-core/*.module + grub-core/*.module.exe + grub-core/*.pp ++grub-core/kernel.img.bin + util/bash-completion.d/grub + grub-core/gnulib/alloca.h + grub-core/gnulib/arg-nonnull.h +diff --git a/ChangeLog b/ChangeLog +index d37d4a6fc16..a49f5f1f48f 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2014-01-29 Paulo Flabiano Smorigo ++ ++ * .gitignore: add missing files and .exe variants. ++ + 2014-01-26 Vladimir Serbinenko + + * grub-core/term/at_keyboard.c: Tolerate missing keyboard. +@@ -1113,7 +1117,7 @@ + + 2013-12-14 Vladimir Serbinenko + +- * .gitignore: Add .exe variants. Add missing files. Remove few outdated ++ * .gitignore: add .exe variants. add missing files. remove few outdated + entries. + + 2013-12-14 Vladimir Serbinenko diff --git a/SOURCES/0050-util-grub-mkfont.c-Downgrade-warnings-about-unhandle.patch b/SOURCES/0050-util-grub-mkfont.c-Downgrade-warnings-about-unhandle.patch new file mode 100644 index 0000000..83a6b08 --- /dev/null +++ b/SOURCES/0050-util-grub-mkfont.c-Downgrade-warnings-about-unhandle.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Wed, 29 Jan 2014 23:41:48 +0100 +Subject: [PATCH] * util/grub-mkfont.c: Downgrade warnings about unhandled + features to debug. + +--- + util/grub-mkfont.c | 14 ++++++++------ + ChangeLog | 9 +++++++++ + 2 files changed, 17 insertions(+), 6 deletions(-) + +diff --git a/util/grub-mkfont.c b/util/grub-mkfont.c +index 3cb02ad5c45..3de07ee9c06 100644 +--- a/util/grub-mkfont.c ++++ b/util/grub-mkfont.c +@@ -516,8 +516,8 @@ process_cursive (struct gsub_feature *feature, + } + if (grub_be_to_cpu16 (lookup->flag) & ~GSUB_RTL_CHAR) + { +- printf (_("Unsupported substitution flag: 0x%x\n"), +- grub_be_to_cpu16 (lookup->flag)); ++ grub_util_info ("unsupported substitution flag: 0x%x", ++ grub_be_to_cpu16 (lookup->flag)); + } + switch (feattag) + { +@@ -577,7 +577,8 @@ process_cursive (struct gsub_feature *feature, + There are 2 coverage specifications: list and range. + This warning is thrown when another coverage specification + is detected. */ +- printf (_("Unsupported coverage specification: %d\n"), covertype); ++ fprintf (stderr, ++ _("Unsupported coverage specification: %d\n"), covertype); + } + } + } +@@ -616,7 +617,8 @@ add_font (struct grub_font_info *font_info, FT_Face face, int nocut) + grub_uint32_t feattag + = grub_be_to_cpu32 (features->features[i].feature_tag); + if (feature->params) +- printf (_("WARNING: unsupported font feature parameters: %x\n"), ++ fprintf (stderr, ++ _("WARNING: unsupported font feature parameters: %x\n"), + grub_be_to_cpu16 (feature->params)); + switch (feattag) + { +@@ -647,8 +649,8 @@ add_font (struct grub_font_info *font_info, FT_Face face, int nocut) + if (!grub_isgraph (str[j])) + str[j] = '?'; + /* TRANSLATORS: It's gsub feature, not gsub font. */ +- printf (_("Unknown gsub font feature 0x%x (%s)\n"), +- feattag, str); ++ grub_util_info ("Unknown gsub font feature 0x%x (%s)", ++ feattag, str); + } + } + } +diff --git a/ChangeLog b/ChangeLog +index a49f5f1f48f..9837c7f8d38 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,12 @@ ++2014-01-29 Vladimir Serbinenko ++ ++ * util/grub-mkfont.c: Downgrade warnings about unhandled features ++ to debug. ++ ++2014-01-29 Vladimir Serbinenko ++ ++ * grub-core/term/at_keyboard.c: Tolerate missing keyboard. ++ + 2014-01-29 Paulo Flabiano Smorigo + + * .gitignore: add missing files and .exe variants. diff --git a/SOURCES/0051-grub-core-disk-ahci.c-Do-not-enable-I-O-decoding-and.patch b/SOURCES/0051-grub-core-disk-ahci.c-Do-not-enable-I-O-decoding-and.patch new file mode 100644 index 0000000..1d852b3 --- /dev/null +++ b/SOURCES/0051-grub-core-disk-ahci.c-Do-not-enable-I-O-decoding-and.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Wed, 29 Jan 2014 23:43:25 +0100 +Subject: [PATCH] * grub-core/disk/ahci.c: Do not enable I/O decoding and keep + enabling busmaster for the end. + +--- + grub-core/disk/ahci.c | 10 ++++++---- + ChangeLog | 5 +++++ + 2 files changed, 11 insertions(+), 4 deletions(-) + +diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c +index 0b13fb8ebed..18c13270c65 100644 +--- a/grub-core/disk/ahci.c ++++ b/grub-core/disk/ahci.c +@@ -194,10 +194,8 @@ grub_ahci_pciinit (grub_pci_device_t dev, + return 0; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); +- grub_pci_write_word (addr, grub_pci_read_word (addr) | +- GRUB_PCI_COMMAND_IO_ENABLED +- | GRUB_PCI_COMMAND_MEM_ENABLED +- | GRUB_PCI_COMMAND_BUS_MASTER); ++ grub_pci_write_word (addr, grub_pci_read_word (addr) ++ | GRUB_PCI_COMMAND_MEM_ENABLED); + + hba = grub_pci_device_map_range (dev, bar & GRUB_PCI_ADDR_MEM_MASK, + sizeof (hba)); +@@ -621,6 +619,10 @@ grub_ahci_pciinit (grub_pci_device_t dev, + if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].sig >> 16) == 0xeb14) + adevs[i]->atapi = 1; + ++ addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); ++ grub_pci_write_word (addr, grub_pci_read_word (addr) ++ | GRUB_PCI_COMMAND_BUS_MASTER); ++ + for (i = 0; i < nports; i++) + if (adevs[i]) + { +diff --git a/ChangeLog b/ChangeLog +index 9837c7f8d38..51eba95f36f 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2014-01-29 Vladimir Serbinenko ++ ++ * grub-core/disk/ahci.c: Do not enable I/O decoding and keep ++ enabling busmaster for the end. ++ + 2014-01-29 Vladimir Serbinenko + + * util/grub-mkfont.c: Downgrade warnings about unhandled features diff --git a/SOURCES/0052-grub-core-disk-ahci.c-Allocate-and-clean-space-for-a.patch b/SOURCES/0052-grub-core-disk-ahci.c-Allocate-and-clean-space-for-a.patch new file mode 100644 index 0000000..d1a4ef9 --- /dev/null +++ b/SOURCES/0052-grub-core-disk-ahci.c-Allocate-and-clean-space-for-a.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Wed, 29 Jan 2014 23:45:18 +0100 +Subject: [PATCH] * grub-core/disk/ahci.c: Allocate and clean space for all + possible 32 slots to avoid pointing to uninited area. + +--- + grub-core/disk/ahci.c | 8 +++++++- + ChangeLog | 5 +++++ + 2 files changed, 12 insertions(+), 1 deletion(-) + +diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c +index 18c13270c65..d63fd09fdc6 100644 +--- a/grub-core/disk/ahci.c ++++ b/grub-core/disk/ahci.c +@@ -358,7 +358,7 @@ grub_ahci_pciinit (grub_pci_device_t dev, + grub_dprintf ("ahci", "err: %x\n", + adevs[i]->hba->ports[adevs[i]->port].sata_error); + +- adevs[i]->command_list_chunk = grub_memalign_dma32 (1024, sizeof (struct grub_ahci_cmd_head)); ++ adevs[i]->command_list_chunk = grub_memalign_dma32 (1024, sizeof (struct grub_ahci_cmd_head) * 32); + if (!adevs[i]->command_list_chunk) + { + adevs[i] = 0; +@@ -376,6 +376,12 @@ grub_ahci_pciinit (grub_pci_device_t dev, + + adevs[i]->command_list = grub_dma_get_virt (adevs[i]->command_list_chunk); + adevs[i]->command_table = grub_dma_get_virt (adevs[i]->command_table_chunk); ++ ++ grub_memset ((void *) adevs[i]->command_list, 0, ++ sizeof (struct grub_ahci_cmd_table)); ++ grub_memset ((void *) adevs[i]->command_table, 0, ++ sizeof (struct grub_ahci_cmd_head) * 32); ++ + adevs[i]->command_list->command_table_base + = grub_dma_get_phys (adevs[i]->command_table_chunk); + +diff --git a/ChangeLog b/ChangeLog +index 51eba95f36f..9bb18177793 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2014-01-29 Vladimir Serbinenko ++ ++ * grub-core/disk/ahci.c: Allocate and clean space for all possible 32 ++ slots to avoid pointing to uninited area. ++ + 2014-01-29 Vladimir Serbinenko + + * grub-core/disk/ahci.c: Do not enable I/O decoding and keep diff --git a/SOURCES/0053-grub-core-disk-ahci.c-Add-safety-cleanups.patch b/SOURCES/0053-grub-core-disk-ahci.c-Add-safety-cleanups.patch new file mode 100644 index 0000000..7a1172a --- /dev/null +++ b/SOURCES/0053-grub-core-disk-ahci.c-Add-safety-cleanups.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Wed, 29 Jan 2014 23:46:17 +0100 +Subject: [PATCH] * grub-core/disk/ahci.c: Add safety cleanups. + +--- + grub-core/disk/ahci.c | 10 ++++++++++ + ChangeLog | 4 ++++ + 2 files changed, 14 insertions(+) + +diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c +index d63fd09fdc6..643e691ef80 100644 +--- a/grub-core/disk/ahci.c ++++ b/grub-core/disk/ahci.c +@@ -454,6 +454,7 @@ grub_ahci_pciinit (grub_pci_device_t dev, + adevs[i]->hba->ports[adevs[i]->port].fis_base = grub_dma_get_phys (adevs[i]->rfis); + adevs[i]->hba->ports[adevs[i]->port].command_list_base + = grub_dma_get_phys (adevs[i]->command_list_chunk); ++ adevs[i]->hba->ports[adevs[i]->port].command_issue = 0; + adevs[i]->hba->ports[adevs[i]->port].command |= GRUB_AHCI_HBA_PORT_CMD_FRE; + } + +@@ -600,6 +601,9 @@ grub_ahci_pciinit (grub_pci_device_t dev, + failed_adevs[i] = adevs[i]; + adevs[i] = 0; + } ++ ++ grub_dprintf ("ahci", "cleaning up failed devs\n"); ++ + for (i = 0; i < nports; i++) + if (failed_adevs[i] && (fr_running & (1 << i))) + failed_adevs[i]->hba->ports[failed_adevs[i]->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; +@@ -855,6 +859,12 @@ grub_ahci_reset_port (struct grub_ahci_device *dev, int force) + { + struct grub_disk_ata_pass_through_parms parms2; + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; ++ dev->hba->ports[dev->port].command_issue = 0; ++ dev->command_list[0].config = 0; ++ dev->command_table[0].prdt[0].unused = 0; ++ dev->command_table[0].prdt[0].size = 0; ++ dev->command_table[0].prdt[0].data_base = 0; ++ + endtime = grub_get_time_ms () + 1000; + while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) + if (grub_get_time_ms () > endtime) +diff --git a/ChangeLog b/ChangeLog +index 9bb18177793..15300b020c6 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2014-01-29 Vladimir Serbinenko ++ ++ * grub-core/disk/ahci.c: Add safety cleanups. ++ + 2014-01-29 Vladimir Serbinenko + + * grub-core/disk/ahci.c: Allocate and clean space for all possible 32 diff --git a/SOURCES/0054-grub-core-disk-ahci.c-Properly-handle-transactions-w.patch b/SOURCES/0054-grub-core-disk-ahci.c-Properly-handle-transactions-w.patch new file mode 100644 index 0000000..11a7c59 --- /dev/null +++ b/SOURCES/0054-grub-core-disk-ahci.c-Properly-handle-transactions-w.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Wed, 29 Jan 2014 23:49:51 +0100 +Subject: [PATCH] * grub-core/disk/ahci.c: Properly handle transactions with no + transferred data. + +--- + grub-core/disk/ahci.c | 7 +++++-- + ChangeLog | 5 +++++ + 2 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c +index 643e691ef80..fdd40c64dd9 100644 +--- a/grub-core/disk/ahci.c ++++ b/grub-core/disk/ahci.c +@@ -932,7 +932,10 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev, + if (parms->size > GRUB_AHCI_PRDT_MAX_CHUNK_LENGTH) + return grub_error (GRUB_ERR_BUG, "too big data buffer"); + +- bufc = grub_memalign_dma32 (1024, parms->size + (parms->size & 1)); ++ if (parms->size) ++ bufc = grub_memalign_dma32 (1024, parms->size + (parms->size & 1)); ++ else ++ bufc = grub_memalign_dma32 (1024, 512); + + grub_dprintf ("ahci", "AHCI tfd = %x, CL=%p\n", + dev->hba->ports[dev->port].task_file_data, +@@ -942,7 +945,7 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev, + = (5 << GRUB_AHCI_CONFIG_CFIS_LENGTH_SHIFT) + // | GRUB_AHCI_CONFIG_CLEAR_R_OK + | (0 << GRUB_AHCI_CONFIG_PMP_SHIFT) +- | (1 << GRUB_AHCI_CONFIG_PRDT_LENGTH_SHIFT) ++ | ((parms->size ? 1 : 0) << GRUB_AHCI_CONFIG_PRDT_LENGTH_SHIFT) + | (parms->cmdsize ? GRUB_AHCI_CONFIG_ATAPI : 0) + | (parms->write ? GRUB_AHCI_CONFIG_WRITE : GRUB_AHCI_CONFIG_READ) + | (parms->taskfile.cmd == 8 ? (1 << 8) : 0); +diff --git a/ChangeLog b/ChangeLog +index 15300b020c6..bc1ab231b02 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2014-01-29 Vladimir Serbinenko ++ ++ * grub-core/disk/ahci.c: Properly handle transactions with no ++ transferred data. ++ + 2014-01-29 Vladimir Serbinenko + + * grub-core/disk/ahci.c: Add safety cleanups. diff --git a/SOURCES/0055-grub-core-disk-ahci.c-Increase-timeout.-Some-SSDs-ta.patch b/SOURCES/0055-grub-core-disk-ahci.c-Increase-timeout.-Some-SSDs-ta.patch new file mode 100644 index 0000000..3430836 --- /dev/null +++ b/SOURCES/0055-grub-core-disk-ahci.c-Increase-timeout.-Some-SSDs-ta.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Wed, 29 Jan 2014 23:50:49 +0100 +Subject: [PATCH] * grub-core/disk/ahci.c: Increase timeout. Some SSDs take up + to 7 seconds to recover if last poweroff was bad. + +--- + grub-core/disk/ahci.c | 2 +- + ChangeLog | 5 +++++ + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c +index fdd40c64dd9..5e4a6397a49 100644 +--- a/grub-core/disk/ahci.c ++++ b/grub-core/disk/ahci.c +@@ -1022,7 +1022,7 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev, + grub_dprintf ("ahci", "AHCI tfd = %x\n", + dev->hba->ports[dev->port].task_file_data); + +- endtime = grub_get_time_ms () + (spinup ? 10000 : 5000); ++ endtime = grub_get_time_ms () + (spinup ? 20000 : 20000); + while ((dev->hba->ports[dev->port].command_issue & 1)) + if (grub_get_time_ms () > endtime) + { +diff --git a/ChangeLog b/ChangeLog +index bc1ab231b02..1a822f3d2f2 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2014-01-29 Vladimir Serbinenko ++ ++ * grub-core/disk/ahci.c: Increase timeout. Some SSDs take up to ++ 7 seconds to recover if last poweroff was bad. ++ + 2014-01-29 Vladimir Serbinenko + + * grub-core/disk/ahci.c: Properly handle transactions with no diff --git a/SOURCES/0056-util-grub-mkfont.c-Build-fix-for-argp.h-with-older-g.patch b/SOURCES/0056-util-grub-mkfont.c-Build-fix-for-argp.h-with-older-g.patch new file mode 100644 index 0000000..bfdec61 --- /dev/null +++ b/SOURCES/0056-util-grub-mkfont.c-Build-fix-for-argp.h-with-older-g.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Mon, 3 Feb 2014 14:34:27 +0100 +Subject: [PATCH] * util/grub-mkfont.c: Build fix for argp.h with older gcc. + +--- + util/grub-mkfont.c | 4 ++++ + ChangeLog | 4 ++++ + 2 files changed, 8 insertions(+) + +diff --git a/util/grub-mkfont.c b/util/grub-mkfont.c +index 3de07ee9c06..e6485b40f28 100644 +--- a/util/grub-mkfont.c ++++ b/util/grub-mkfont.c +@@ -33,7 +33,11 @@ + + #ifndef GRUB_BUILD + #define _GNU_SOURCE 1 ++#pragma GCC diagnostic ignored "-Wmissing-prototypes" ++#pragma GCC diagnostic ignored "-Wmissing-declarations" + #include ++#pragma GCC diagnostic error "-Wmissing-prototypes" ++#pragma GCC diagnostic error "-Wmissing-declarations" + #endif + #include + +diff --git a/ChangeLog b/ChangeLog +index 1a822f3d2f2..f2bba8402c5 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2014-02-03 Vladimir Serbinenko ++ ++ * util/grub-mkfont.c: Build fix for argp.h with older gcc. ++ + 2014-01-29 Vladimir Serbinenko + + * grub-core/disk/ahci.c: Increase timeout. Some SSDs take up to diff --git a/SOURCES/0057-util-grub-mkrescue.c-Build-fix-for-argp.h-with-older.patch b/SOURCES/0057-util-grub-mkrescue.c-Build-fix-for-argp.h-with-older.patch new file mode 100644 index 0000000..441b0e4 --- /dev/null +++ b/SOURCES/0057-util-grub-mkrescue.c-Build-fix-for-argp.h-with-older.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Mon, 3 Feb 2014 14:35:51 +0100 +Subject: [PATCH] * util/grub-mkrescue.c: Build fix for argp.h with older gcc. + +--- + util/grub-mkrescue.c | 4 ++++ + ChangeLog | 4 ++++ + 2 files changed, 8 insertions(+) + +diff --git a/util/grub-mkrescue.c b/util/grub-mkrescue.c +index 34e0b7affb1..e719839820b 100644 +--- a/util/grub-mkrescue.c ++++ b/util/grub-mkrescue.c +@@ -25,7 +25,11 @@ + #include + #include + #include ++#pragma GCC diagnostic ignored "-Wmissing-prototypes" ++#pragma GCC diagnostic ignored "-Wmissing-declarations" + #include ++#pragma GCC diagnostic error "-Wmissing-prototypes" ++#pragma GCC diagnostic error "-Wmissing-declarations" + + #include + #include +diff --git a/ChangeLog b/ChangeLog +index f2bba8402c5..f4a472144b1 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2014-02-03 Vladimir Serbinenko ++ ++ * util/grub-mkrescue.c: Build fix for argp.h with older gcc. ++ + 2014-02-03 Vladimir Serbinenko + + * util/grub-mkfont.c: Build fix for argp.h with older gcc. diff --git a/SOURCES/0058-add-grub_env_set_net_property-function.patch b/SOURCES/0058-add-grub_env_set_net_property-function.patch new file mode 100644 index 0000000..10e37d0 --- /dev/null +++ b/SOURCES/0058-add-grub_env_set_net_property-function.patch @@ -0,0 +1,196 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paulo Flabiano Smorigo +Date: Tue, 4 Feb 2014 18:41:38 -0200 +Subject: [PATCH] add grub_env_set_net_property function + +* grub-core/net/bootp.c: Remove set_env_limn_ro. +* grub-core/net/net.c: Add grub_env_set_net_property. +* include/grub/net.h: Likewise. +--- + grub-core/net/bootp.c | 63 +++++++++++++-------------------------------------- + grub-core/net/net.c | 38 +++++++++++++++++++++++++++++++ + include/grub/net.h | 4 ++++ + ChangeLog | 8 +++++++ + 4 files changed, 66 insertions(+), 47 deletions(-) + +diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c +index c14e9de57a4..6310ed447e8 100644 +--- a/grub-core/net/bootp.c ++++ b/grub-core/net/bootp.c +@@ -25,41 +25,6 @@ + #include + #include + +-static char * +-grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)), +- const char *val __attribute__ ((unused))) +-{ +- return NULL; +-} +- +-static void +-set_env_limn_ro (const char *intername, const char *suffix, +- const char *value, grub_size_t len) +-{ +- char *varname, *varvalue; +- char *ptr; +- varname = grub_xasprintf ("net_%s_%s", intername, suffix); +- if (!varname) +- return; +- for (ptr = varname; *ptr; ptr++) +- if (*ptr == ':') +- *ptr = '_'; +- varvalue = grub_malloc (len + 1); +- if (!varvalue) +- { +- grub_free (varname); +- return; +- } +- +- grub_memcpy (varvalue, value, len); +- varvalue[len] = 0; +- grub_env_set (varname, varvalue); +- grub_register_variable_hook (varname, 0, grub_env_write_readonly); +- grub_env_export (varname); +- grub_free (varname); +- grub_free (varvalue); +-} +- + static void + parse_dhcp_vendor (const char *name, const void *vend, int limit, int *mask) + { +@@ -136,20 +101,24 @@ parse_dhcp_vendor (const char *name, const void *vend, int limit, int *mask) + } + continue; + case GRUB_NET_BOOTP_HOSTNAME: +- set_env_limn_ro (name, "hostname", (const char *) ptr, taglength); +- break; ++ grub_env_set_net_property (name, "hostname", (const char *) ptr, ++ taglength); ++ break; + + case GRUB_NET_BOOTP_DOMAIN: +- set_env_limn_ro (name, "domain", (const char *) ptr, taglength); +- break; ++ grub_env_set_net_property (name, "domain", (const char *) ptr, ++ taglength); ++ break; + + case GRUB_NET_BOOTP_ROOT_PATH: +- set_env_limn_ro (name, "rootpath", (const char *) ptr, taglength); +- break; ++ grub_env_set_net_property (name, "rootpath", (const char *) ptr, ++ taglength); ++ break; + + case GRUB_NET_BOOTP_EXTENSIONS_PATH: +- set_env_limn_ro (name, "extensionspath", (const char *) ptr, taglength); +- break; ++ grub_env_set_net_property (name, "extensionspath", (const char *) ptr, ++ taglength); ++ break; + + /* If you need any other options please contact GRUB + development team. */ +@@ -211,8 +180,8 @@ grub_net_configure_by_dhcp_ack (const char *name, + } + + if (size > OFFSET_OF (boot_file, bp)) +- set_env_limn_ro (name, "boot_file", (char *) bp->boot_file, +- sizeof (bp->boot_file)); ++ 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) +@@ -243,8 +212,8 @@ grub_net_configure_by_dhcp_ack (const char *name, + if (size > OFFSET_OF (server_name, bp) + && bp->server_name[0]) + { +- set_env_limn_ro (name, "dhcp_server_name", (char *) bp->server_name, +- sizeof (bp->server_name)); ++ grub_env_set_net_property (name, "dhcp_server_name", bp->server_name, ++ sizeof (bp->server_name)); + if (is_def && !grub_net_default_server) + { + grub_net_default_server = grub_strdup (bp->server_name); +diff --git a/grub-core/net/net.c b/grub-core/net/net.c +index 1521d8d2c87..f2e723bd409 100644 +--- a/grub-core/net/net.c ++++ b/grub-core/net/net.c +@@ -1480,6 +1480,44 @@ receive_packets (struct grub_net_card *card, int *stop_condition) + grub_print_error (); + } + ++static char * ++grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)), ++ const char *val __attribute__ ((unused))) ++{ ++ return NULL; ++} ++ ++grub_err_t ++grub_env_set_net_property (const char *intername, const char *suffix, ++ const char *value, grub_size_t len) ++{ ++ char *varname, *varvalue; ++ char *ptr; ++ ++ varname = grub_xasprintf ("net_%s_%s", intername, suffix); ++ if (!varname) ++ return grub_errno; ++ for (ptr = varname; *ptr; ptr++) ++ if (*ptr == ':') ++ *ptr = '_'; ++ varvalue = grub_malloc (len + 1); ++ if (!varvalue) ++ { ++ grub_free (varname); ++ return grub_errno; ++ } ++ ++ grub_memcpy (varvalue, value, len); ++ varvalue[len] = 0; ++ grub_err_t ret = grub_env_set (varname, varvalue); ++ grub_register_variable_hook (varname, 0, grub_env_write_readonly); ++ grub_env_export (varname); ++ grub_free (varname); ++ grub_free (varvalue); ++ ++ return ret; ++} ++ + void + grub_net_poll_cards (unsigned time, int *stop_condition) + { +diff --git a/include/grub/net.h b/include/grub/net.h +index 0e0a605c5a6..538baa33eca 100644 +--- a/include/grub/net.h ++++ b/include/grub/net.h +@@ -480,6 +480,10 @@ grub_net_addr_to_str (const grub_net_network_level_address_t *target, + void + grub_net_hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str); + ++grub_err_t ++grub_env_set_net_property (const char *intername, const char *suffix, ++ const char *value, grub_size_t len); ++ + void + grub_net_poll_cards (unsigned time, int *stop_condition); + +diff --git a/ChangeLog b/ChangeLog +index f4a472144b1..63f5aa322c3 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,11 @@ ++2014-02-04 Paulo Flabiano Smorigo ++ ++ Add grub_env_set_net_property function. ++ ++ * grub-core/net/bootp.c: Remove set_env_limn_ro. ++ * grub-core/net/net.c: Add grub_env_set_net_property. ++ * include/grub/net.h: Likewise. ++ + 2014-02-03 Vladimir Serbinenko + + * util/grub-mkrescue.c: Build fix for argp.h with older gcc. diff --git a/SOURCES/0059-add-bootpath-parser-for-open-firmware.patch b/SOURCES/0059-add-bootpath-parser-for-open-firmware.patch new file mode 100644 index 0000000..51e6cf7 --- /dev/null +++ b/SOURCES/0059-add-bootpath-parser-for-open-firmware.patch @@ -0,0 +1,206 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paulo Flabiano Smorigo +Date: Tue, 4 Feb 2014 19:00:55 -0200 +Subject: [PATCH] add bootpath parser for open firmware + +It enables net boot even when there is no bootp/dhcp server. + +* grub-core/net/drivers/ieee1275/ofnet.c: Add grub_ieee1275_parse_bootpath and +call it at grub_ieee1275_net_config_real. +* grub-core/kern/ieee1275/init.c: Add bootpath to grub_ieee1275_net_config. +* include/grub/ieee1275/ieee1275.h: Likewise. +--- + grub-core/kern/ieee1275/init.c | 7 +-- + grub-core/net/drivers/ieee1275/ofnet.c | 107 ++++++++++++++++++++++++++++++++- + include/grub/ieee1275/ieee1275.h | 5 +- + ChangeLog | 13 ++++ + 4 files changed, 125 insertions(+), 7 deletions(-) + +diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c +index 89b2822e14d..d5bd74d3552 100644 +--- a/grub-core/kern/ieee1275/init.c ++++ b/grub-core/kern/ieee1275/init.c +@@ -80,9 +80,8 @@ grub_translate_ieee1275_path (char *filepath) + } + } + +-void (*grub_ieee1275_net_config) (const char *dev, +- char **device, +- char **path); ++void (*grub_ieee1275_net_config) (const char *dev, char **device, char **path, ++ char *bootpath); + void + grub_machine_get_bootlocation (char **device, char **path) + { +@@ -126,7 +125,7 @@ grub_machine_get_bootlocation (char **device, char **path) + *ptr = 0; + + if (grub_ieee1275_net_config) +- grub_ieee1275_net_config (canon, device, path); ++ grub_ieee1275_net_config (canon, device, path, bootpath); + grub_free (dev); + grub_free (canon); + } +diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c +index 4483c9122f7..eea8e71d300 100644 +--- a/grub-core/net/drivers/ieee1275/ofnet.c ++++ b/grub-core/net/drivers/ieee1275/ofnet.c +@@ -127,8 +127,111 @@ bootp_response_properties[] = + { .name = "bootpreply-packet", .offset = 0x2a}, + }; + ++enum ++{ ++ BOOTARGS_SERVER_ADDR, ++ BOOTARGS_FILENAME, ++ BOOTARGS_CLIENT_ADDR, ++ BOOTARGS_GATEWAY_ADDR, ++ BOOTARGS_BOOTP_RETRIES, ++ BOOTARGS_TFTP_RETRIES, ++ BOOTARGS_SUBNET_MASK, ++ BOOTARGS_BLOCKSIZE ++}; ++ ++static int ++grub_ieee1275_parse_bootpath (const char *devpath, char *bootpath, ++ char **device, struct grub_net_card **card) ++{ ++ char *args; ++ char *comma_char = 0; ++ char *equal_char = 0; ++ grub_size_t field_counter = 0; ++ ++ grub_net_network_level_address_t client_addr, gateway_addr, subnet_mask; ++ grub_net_link_level_address_t hw_addr; ++ grub_net_interface_flags_t flags = 0; ++ struct grub_net_network_level_interface *inter; ++ ++ hw_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; ++ ++ args = bootpath + grub_strlen (devpath) + 1; ++ do ++ { ++ comma_char = grub_strchr (args, ','); ++ if (comma_char != 0) ++ *comma_char = 0; ++ ++ /* Check if it's an option (like speed=auto) and not a default parameter */ ++ equal_char = grub_strchr (args, '='); ++ if (equal_char != 0) ++ { ++ *equal_char = 0; ++ grub_env_set_net_property ((*card)->name, args, equal_char + 1, ++ grub_strlen(equal_char + 1)); ++ *equal_char = '='; ++ } ++ else ++ { ++ switch (field_counter++) ++ { ++ case BOOTARGS_SERVER_ADDR: ++ *device = grub_xasprintf ("tftp,%s", args); ++ if (!*device) ++ return grub_errno; ++ break; ++ ++ case BOOTARGS_CLIENT_ADDR: ++ grub_net_resolve_address (args, &client_addr); ++ break; ++ ++ case BOOTARGS_GATEWAY_ADDR: ++ grub_net_resolve_address (args, &gateway_addr); ++ break; ++ ++ case BOOTARGS_SUBNET_MASK: ++ grub_net_resolve_address (args, &subnet_mask); ++ break; ++ } ++ } ++ args = comma_char + 1; ++ if (comma_char != 0) ++ *comma_char = ','; ++ } while (comma_char != 0); ++ ++ if ((client_addr.ipv4 != 0) && (subnet_mask.ipv4 != 0)) ++ { ++ grub_ieee1275_phandle_t devhandle; ++ grub_ieee1275_finddevice (devpath, &devhandle); ++ grub_ieee1275_get_property (devhandle, "mac-address", ++ hw_addr.mac, sizeof(hw_addr.mac), 0); ++ inter = grub_net_add_addr ((*card)->name, *card, &client_addr, &hw_addr, ++ flags); ++ grub_net_add_ipv4_local (inter, ++ __builtin_ctz (~grub_le_to_cpu32 (subnet_mask.ipv4))); ++ } ++ ++ if (gateway_addr.ipv4 != 0) ++ { ++ grub_net_network_level_netaddress_t target; ++ char *rname; ++ ++ target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; ++ target.ipv4.base = 0; ++ target.ipv4.masksize = 0; ++ rname = grub_xasprintf ("%s:default", ((*card)->name)); ++ if (rname) ++ grub_net_add_route_gw (rname, target, gateway_addr); ++ else ++ return grub_errno; ++ } ++ ++ return 0; ++} ++ + static void +-grub_ieee1275_net_config_real (const char *devpath, char **device, char **path) ++grub_ieee1275_net_config_real (const char *devpath, char **device, char **path, ++ char *bootpath) + { + struct grub_net_card *card; + +@@ -158,6 +261,8 @@ grub_ieee1275_net_config_real (const char *devpath, char **device, char **path) + } + grub_free (canon); + ++ grub_ieee1275_parse_bootpath (devpath, bootpath, device, &card); ++ + for (i = 0; i < ARRAY_SIZE (bootp_response_properties); i++) + if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, + bootp_response_properties[i].name, +diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h +index dc54beabb4b..8e425130327 100644 +--- a/include/grub/ieee1275/ieee1275.h ++++ b/include/grub/ieee1275/ieee1275.h +@@ -70,8 +70,9 @@ struct grub_ieee1275_devalias + }; + + extern void (*EXPORT_VAR(grub_ieee1275_net_config)) (const char *dev, +- char **device, +- char **path); ++ char **device, ++ char **path, ++ char *bootargs); + + /* Maps a device alias to a pathname. */ + extern grub_ieee1275_phandle_t EXPORT_VAR(grub_ieee1275_chosen); +diff --git a/ChangeLog b/ChangeLog +index 63f5aa322c3..5237631583a 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,16 @@ ++2014-02-04 Paulo Flabiano Smorigo ++ ++ Add bootpath parser for open firmware. ++ ++ It enables net boot even when there is no bootp/dhcp server. ++ ++ * grub-core/net/drivers/ieee1275/ofnet.c: Add grub_ieee1275_parse_bootpath ++ and call it at grub_ieee1275_net_config_real. ++ * grub-core/kern/ieee1275/init.c: Add bootpath to ++ grub_ieee1275_net_config. ++ * include/grub/ieee1275/ieee1275.h: Likewise. ++ ++ + 2014-02-04 Paulo Flabiano Smorigo + + Add grub_env_set_net_property function. diff --git a/SOURCES/0060-grub-core-disk-ahci.c-Ignore-NPORTS-field-and-rely-o.patch b/SOURCES/0060-grub-core-disk-ahci.c-Ignore-NPORTS-field-and-rely-o.patch new file mode 100644 index 0000000..6875b14 --- /dev/null +++ b/SOURCES/0060-grub-core-disk-ahci.c-Ignore-NPORTS-field-and-rely-o.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Thu, 20 Feb 2014 10:11:43 +0100 +Subject: [PATCH] * grub-core/disk/ahci.c: Ignore NPORTS field and rely on PI + exclusively. + +--- + grub-core/disk/ahci.c | 2 +- + ChangeLog | 5 +++++ + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c +index 5e4a6397a49..89365cd0925 100644 +--- a/grub-core/disk/ahci.c ++++ b/grub-core/disk/ahci.c +@@ -322,7 +322,7 @@ grub_ahci_pciinit (grub_pci_device_t dev, + + grub_dprintf ("ahci", "GLC:%x\n", hba->global_control); + +- nports = (hba->cap & GRUB_AHCI_HBA_CAP_NPORTS_MASK) + 1; ++ nports = (GRUB_AHCI_HBA_CAP_NPORTS_MASK) + 1; + + grub_dprintf ("ahci", "%d AHCI ports, PI = 0x%x\n", nports, + hba->ports_implemented); +diff --git a/ChangeLog b/ChangeLog +index 5237631583a..be41aa51f65 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2014-02-20 Vladimir Serbinenko ++ ++ * grub-core/disk/ahci.c: Ignore NPORTS field and rely on PI ++ exclusively. ++ + 2014-02-04 Paulo Flabiano Smorigo + + Add bootpath parser for open firmware. diff --git a/SOURCES/0061-grub-core-kern-i386-coreboot-mmap.c-Filter-out-0xa00.patch b/SOURCES/0061-grub-core-kern-i386-coreboot-mmap.c-Filter-out-0xa00.patch new file mode 100644 index 0000000..e3839f4 --- /dev/null +++ b/SOURCES/0061-grub-core-kern-i386-coreboot-mmap.c-Filter-out-0xa00.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Fri, 28 Feb 2014 09:47:57 +0100 +Subject: [PATCH] * grub-core/kern/i386/coreboot/mmap.c: Filter out + 0xa0000-0x100000 region. + +--- + grub-core/kern/i386/coreboot/mmap.c | 38 +++++++++++++++++++++++++++++++------ + ChangeLog | 5 +++++ + 2 files changed, 37 insertions(+), 6 deletions(-) + +diff --git a/grub-core/kern/i386/coreboot/mmap.c b/grub-core/kern/i386/coreboot/mmap.c +index 11979755144..4d29f6b7d90 100644 +--- a/grub-core/kern/i386/coreboot/mmap.c ++++ b/grub-core/kern/i386/coreboot/mmap.c +@@ -44,18 +44,44 @@ iterate_linuxbios_table (grub_linuxbios_table_item_t table_item, void *data) + mem_region = + (mem_region_t) ((long) table_item + + sizeof (struct grub_linuxbios_table_item)); +- while ((long) mem_region < (long) table_item + (long) table_item->size) ++ for (; (long) mem_region < (long) table_item + (long) table_item->size; ++ mem_region++) + { +- if (ctx->hook (mem_region->addr, mem_region->size, ++ grub_uint64_t start = mem_region->addr; ++ grub_uint64_t end = mem_region->addr + mem_region->size; ++ /* Mark region 0xa0000 - 0x100000 as reserved. */ ++ if (start < 0x100000 && end >= 0xa0000 ++ && mem_region->type == GRUB_MACHINE_MEMORY_AVAILABLE) ++ { ++ if (start < 0xa0000 ++ && ctx->hook (start, 0xa0000 - start, ++ /* Multiboot mmaps match with the coreboot mmap ++ definition. Therefore, we can just pass type ++ through. */ ++ mem_region->type, ++ ctx->hook_data)) ++ return 1; ++ if (start < 0xa0000) ++ start = 0xa0000; ++ if (start >= end) ++ continue; ++ ++ if (ctx->hook (start, (end > 0x100000 ? 0x100000 : end) - start, ++ GRUB_MEMORY_RESERVED, ++ ctx->hook_data)) ++ return 1; ++ start = 0x100000; ++ ++ if (end <= start) ++ continue; ++ } ++ if (ctx->hook (start, end - start, + /* Multiboot mmaps match with the coreboot mmap + definition. Therefore, we can just pass type + through. */ +- (((mem_region->type <= GRUB_MACHINE_MEMORY_BADRAM) && (mem_region->type >= GRUB_MACHINE_MEMORY_AVAILABLE)) +- || mem_region->type == GRUB_MEMORY_COREBOOT_TABLES) ? mem_region->type : GRUB_MEMORY_RESERVED, ++ mem_region->type, + ctx->hook_data)) + return 1; +- +- mem_region++; + } + + return 0; +diff --git a/ChangeLog b/ChangeLog +index be41aa51f65..4f6f6d6d35a 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2014-02-28 Vladimir Serbinenko ++ ++ * grub-core/kern/i386/coreboot/mmap.c: Filter out 0xa0000-0x100000 ++ region. ++ + 2014-02-20 Vladimir Serbinenko + + * grub-core/disk/ahci.c: Ignore NPORTS field and rely on PI diff --git a/SOURCES/0062-grub-core-loader-i386-multiboot_mbi.c-grub_multiboot.patch b/SOURCES/0062-grub-core-loader-i386-multiboot_mbi.c-grub_multiboot.patch new file mode 100644 index 0000000..3319170 --- /dev/null +++ b/SOURCES/0062-grub-core-loader-i386-multiboot_mbi.c-grub_multiboot.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Fri, 28 Feb 2014 09:48:57 +0100 +Subject: [PATCH] * grub-core/loader/i386/multiboot_mbi.c + (grub_multiboot_make_mbi): Limit location to 640K. + +--- + grub-core/loader/i386/multiboot_mbi.c | 2 +- + ChangeLog | 5 +++++ + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/grub-core/loader/i386/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c +index 7431aa49bbe..f10c087f724 100644 +--- a/grub-core/loader/i386/multiboot_mbi.c ++++ b/grub-core/loader/i386/multiboot_mbi.c +@@ -446,7 +446,7 @@ grub_multiboot_make_mbi (grub_uint32_t *target) + bufsize = grub_multiboot_get_mbi_size (); + + err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch, +- 0x10000, 0x100000 - bufsize, ++ 0x10000, 0xa0000 - bufsize, + bufsize, 4, + GRUB_RELOCATOR_PREFERENCE_NONE, 0); + if (err) +diff --git a/ChangeLog b/ChangeLog +index 4f6f6d6d35a..bbaed2691c7 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2014-02-28 Vladimir Serbinenko ++ ++ * grub-core/loader/i386/multiboot_mbi.c (grub_multiboot_make_mbi): Limit ++ location to 640K. ++ + 2014-02-28 Vladimir Serbinenko + + * grub-core/kern/i386/coreboot/mmap.c: Filter out 0xa0000-0x100000 diff --git a/SOURCES/0063-grub-core-mmap-i386-uppermem.c-lower_hook-COREBOOT-I.patch b/SOURCES/0063-grub-core-mmap-i386-uppermem.c-lower_hook-COREBOOT-I.patch new file mode 100644 index 0000000..78c780e --- /dev/null +++ b/SOURCES/0063-grub-core-mmap-i386-uppermem.c-lower_hook-COREBOOT-I.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Fri, 28 Feb 2014 09:50:47 +0100 +Subject: [PATCH] * grub-core/mmap/i386/uppermem.c (lower_hook) [COREBOOT]: + Ignore low tables for low memory calculations. + +--- + grub-core/mmap/i386/uppermem.c | 6 +++++- + ChangeLog | 5 +++++ + 2 files changed, 10 insertions(+), 1 deletion(-) + +diff --git a/grub-core/mmap/i386/uppermem.c b/grub-core/mmap/i386/uppermem.c +index bd8b429c4be..a6be9896d82 100644 +--- a/grub-core/mmap/i386/uppermem.c ++++ b/grub-core/mmap/i386/uppermem.c +@@ -31,8 +31,12 @@ lower_hook (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type, + + if (type != GRUB_MEMORY_AVAILABLE) + return 0; ++#ifdef GRUB_MACHINE_COREBOOT ++ if (addr <= 0x1000) ++#else + if (addr == 0) +- *lower = size; ++#endif ++ *lower = size + addr; + return 0; + } + +diff --git a/ChangeLog b/ChangeLog +index bbaed2691c7..6ed6cf4ec2b 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2014-02-28 Vladimir Serbinenko ++ ++ * grub-core/mmap/i386/uppermem.c (lower_hook) [COREBOOT]: Ignore low ++ tables for low memory calculations. ++ + 2014-02-28 Vladimir Serbinenko + + * grub-core/loader/i386/multiboot_mbi.c (grub_multiboot_make_mbi): Limit diff --git a/SOURCES/0064-grub-core-kern-i386-pc-mmap.c-Fallback-to-EISA-memor.patch b/SOURCES/0064-grub-core-kern-i386-pc-mmap.c-Fallback-to-EISA-memor.patch new file mode 100644 index 0000000..933e08c --- /dev/null +++ b/SOURCES/0064-grub-core-kern-i386-pc-mmap.c-Fallback-to-EISA-memor.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Fri, 28 Feb 2014 10:07:11 +0100 +Subject: [PATCH] * grub-core/kern/i386/pc/mmap.c: Fallback to EISA memory map + if E820 failed to return any regions. + +--- + grub-core/kern/i386/pc/mmap.c | 40 +++++++++++++++++++++------------------- + ChangeLog | 5 +++++ + 2 files changed, 26 insertions(+), 19 deletions(-) + +diff --git a/grub-core/kern/i386/pc/mmap.c b/grub-core/kern/i386/pc/mmap.c +index 8009e833c1a..f1375f3e12d 100644 +--- a/grub-core/kern/i386/pc/mmap.c ++++ b/grub-core/kern/i386/pc/mmap.c +@@ -141,33 +141,35 @@ grub_get_mmap_entry (struct grub_machine_mmap_entry *entry, + grub_err_t + grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) + { +- grub_uint32_t cont; ++ grub_uint32_t cont = 0; + struct grub_machine_mmap_entry *entry + = (struct grub_machine_mmap_entry *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; ++ int e820_works = 0; + +- grub_memset (entry, 0, sizeof (entry)); ++ while (1) ++ { ++ grub_memset (entry, 0, sizeof (entry)); + +- /* Check if grub_get_mmap_entry works. */ +- cont = grub_get_mmap_entry (entry, 0); ++ cont = grub_get_mmap_entry (entry, cont); + +- if (entry->size) +- do +- { +- if (hook (entry->addr, entry->len, +- /* GRUB mmaps have been defined to match with the E820 definition. +- Therefore, we can just pass type through. */ +- entry->type, hook_data)) +- break; ++ if (!entry->size) ++ break; + +- if (! cont) +- break; ++ if (entry->len) ++ e820_works = 1; ++ if (entry->len ++ && hook (entry->addr, entry->len, ++ /* GRUB mmaps have been defined to match with ++ the E820 definition. ++ Therefore, we can just pass type through. */ ++ entry->type, hook_data)) ++ break; + +- grub_memset (entry, 0, sizeof (entry)); ++ if (! cont) ++ break; ++ } + +- cont = grub_get_mmap_entry (entry, cont); +- } +- while (entry->size); +- else ++ if (!e820_works) + { + grub_uint32_t eisa_mmap = grub_get_eisa_mmap (); + +diff --git a/ChangeLog b/ChangeLog +index 6ed6cf4ec2b..97cf57e253d 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2014-02-28 Vladimir Serbinenko ++ ++ * grub-core/kern/i386/pc/mmap.c: Fallback to EISA memory map ++ if E820 failed to return any regions. ++ + 2014-02-28 Vladimir Serbinenko + + * grub-core/mmap/i386/uppermem.c (lower_hook) [COREBOOT]: Ignore low diff --git a/SOURCES/0065-include-grub-i386-openbsd_bootarg.h-Add-addr-and-fre.patch b/SOURCES/0065-include-grub-i386-openbsd_bootarg.h-Add-addr-and-fre.patch new file mode 100644 index 0000000..f6b2546 --- /dev/null +++ b/SOURCES/0065-include-grub-i386-openbsd_bootarg.h-Add-addr-and-fre.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Fri, 28 Feb 2014 10:50:05 +0100 +Subject: [PATCH] * include/grub/i386/openbsd_bootarg.h: Add addr and frequency + fields. * grub-core/loader/i386/bsd.c (grub_cmd_openbsd): Fill addr field. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + + Suggested by: Markus Müller. +--- + grub-core/loader/i386/bsd.c | 2 ++ + include/grub/i386/openbsd_bootarg.h | 2 ++ + ChangeLog | 7 +++++++ + 3 files changed, 11 insertions(+) + +diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c +index ea0edfafe57..19985f03e65 100644 +--- a/grub-core/loader/i386/bsd.c ++++ b/grub-core/loader/i386/bsd.c +@@ -1646,6 +1646,7 @@ grub_cmd_openbsd (grub_extcmd_context_t ctxt, int argc, char *argv[]) + + serial.device = (GRUB_OPENBSD_COM_MAJOR << 8) | port; + serial.speed = speed; ++ serial.addr = grub_ns8250_hw_get_port (port); + + grub_bsd_add_meta (OPENBSD_BOOTARG_CONSOLE, &serial, sizeof (serial)); + bootflags |= OPENBSD_RB_SERCONS; +@@ -1656,6 +1657,7 @@ grub_cmd_openbsd (grub_extcmd_context_t ctxt, int argc, char *argv[]) + + grub_memset (&serial, 0, sizeof (serial)); + serial.device = (GRUB_OPENBSD_VGA_MAJOR << 8); ++ serial.addr = 0xffffffff; + grub_bsd_add_meta (OPENBSD_BOOTARG_CONSOLE, &serial, sizeof (serial)); + bootflags &= ~OPENBSD_RB_SERCONS; + } +diff --git a/include/grub/i386/openbsd_bootarg.h b/include/grub/i386/openbsd_bootarg.h +index 01ca4868b25..9ebe6b4e4b1 100644 +--- a/include/grub/i386/openbsd_bootarg.h ++++ b/include/grub/i386/openbsd_bootarg.h +@@ -75,6 +75,8 @@ struct grub_openbsd_bootarg_console + { + grub_uint32_t device; + grub_uint32_t speed; ++ grub_uint32_t addr; ++ grub_uint32_t frequency; + }; + + struct grub_openbsd_bootarg_pcibios +diff --git a/ChangeLog b/ChangeLog +index 97cf57e253d..f571f66533b 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,10 @@ ++2014-02-28 Vladimir Serbinenko ++ ++ * include/grub/i386/openbsd_bootarg.h: Add addr and frequency fields. ++ * grub-core/loader/i386/bsd.c (grub_cmd_openbsd): Fill addr field. ++ ++ Suggested by: Markus Müller. ++ + 2014-02-28 Vladimir Serbinenko + + * grub-core/kern/i386/pc/mmap.c: Fallback to EISA memory map diff --git a/SOURCES/0066-ieee1275-check-for-IBM-pseries-emulated-machine.patch b/SOURCES/0066-ieee1275-check-for-IBM-pseries-emulated-machine.patch new file mode 100644 index 0000000..2952449 --- /dev/null +++ b/SOURCES/0066-ieee1275-check-for-IBM-pseries-emulated-machine.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Nikunj A Dadhania +Date: Thu, 20 Mar 2014 16:57:12 +0530 +Subject: [PATCH] ieee1275: check for IBM pseries emulated machine + +is_qemu is not being set lead to disabling of feature like +GRUB_IEEE1275_FLAG_HAS_CURSORONOFF. This resulted in cursor not being +displayed during the grub-menu edit. + +Signed-off-by: Nikunj A Dadhania +--- + grub-core/kern/ieee1275/cmain.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/grub-core/kern/ieee1275/cmain.c b/grub-core/kern/ieee1275/cmain.c +index d92ae14f53e..3e12e6b24e1 100644 +--- a/grub-core/kern/ieee1275/cmain.c ++++ b/grub-core/kern/ieee1275/cmain.c +@@ -84,8 +84,10 @@ grub_ieee1275_find_options (void) + + rc = grub_ieee1275_get_property (root, "model", + tmp, sizeof (tmp), 0); +- if (rc >= 0 && !grub_strcmp (tmp, "Emulated PC")) ++ if (rc >= 0 && (!grub_strcmp (tmp, "Emulated PC") ++ || !grub_strcmp (tmp, "IBM pSeries (emulated by qemu)"))) { + is_qemu = 1; ++ } + + if (rc >= 0 && grub_strncmp (tmp, "IBM", 3) == 0) + grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS); diff --git a/SOURCES/0067-grub-core-loader-arm64-linux.c-Remove-redundant-0x.patch b/SOURCES/0067-grub-core-loader-arm64-linux.c-Remove-redundant-0x.patch new file mode 100644 index 0000000..1188a42 --- /dev/null +++ b/SOURCES/0067-grub-core-loader-arm64-linux.c-Remove-redundant-0x.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Fu Wei +Date: Wed, 26 Mar 2014 08:13:07 +0100 +Subject: [PATCH] * grub-core/loader/arm64/linux.c: Remove redundant "0x". + +--- + grub-core/loader/arm64/linux.c | 2 +- + ChangeLog | 4 ++++ + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c +index 65129c21a8d..f1d10a16492 100644 +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -68,7 +68,7 @@ get_firmware_fdt (void) + if (grub_memcmp (&tables[i].vendor_guid, &fdt_guid, sizeof (fdt_guid)) == 0) + { + firmware_fdt = tables[i].vendor_table; +- grub_dprintf ("linux", "found registered FDT @ 0x%p\n", firmware_fdt); ++ grub_dprintf ("linux", "found registered FDT @ %p\n", firmware_fdt); + break; + } + +diff --git a/ChangeLog b/ChangeLog +index f571f66533b..091535beb5c 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2014-03-26 Fu Wei ++ ++ * grub-core/loader/arm64/linux.c: Remove redundant "0x". ++ + 2014-02-28 Vladimir Serbinenko + + * include/grub/i386/openbsd_bootarg.h: Add addr and frequency fields. diff --git a/SOURCES/0068-grub-core-lib-relocator.c-Fix-the-case-when-end-of-l.patch b/SOURCES/0068-grub-core-lib-relocator.c-Fix-the-case-when-end-of-l.patch new file mode 100644 index 0000000..9f0d9c3 --- /dev/null +++ b/SOURCES/0068-grub-core-lib-relocator.c-Fix-the-case-when-end-of-l.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Wed, 26 Mar 2014 08:48:30 +0100 +Subject: [PATCH] * grub-core/lib/relocator.c: Fix the case when end of + leftover is used. + +--- + grub-core/lib/relocator.c | 2 ++ + ChangeLog | 4 ++++ + 2 files changed, 6 insertions(+) + +diff --git a/grub-core/lib/relocator.c b/grub-core/lib/relocator.c +index 9f9770bc48d..cb11ea5fa27 100644 +--- a/grub-core/lib/relocator.c ++++ b/grub-core/lib/relocator.c +@@ -865,6 +865,8 @@ malloc_in_range (struct grub_relocator *rel, + % GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT; + struct grub_relocator_fw_leftover *lo + = events[last_lo].leftover; ++ if (offend == 0 && alloc_end != alloc_start) ++ offend = GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT; + lo->freebytes[offstart / 8] + &= ((1 << (8 - (start % 8))) - 1); + grub_memset (lo->freebytes + (offstart + 7) / 8, 0, +diff --git a/ChangeLog b/ChangeLog +index 091535beb5c..9404edab8e1 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2014-03-26 Vladimir Serbinenko ++ ++ * grub-core/lib/relocator.c: Fix the case when end of leftover is used. ++ + 2014-03-26 Fu Wei + + * grub-core/loader/arm64/linux.c: Remove redundant "0x". diff --git a/SOURCES/0069-Fix-grub-probe-0-option.patch b/SOURCES/0069-Fix-grub-probe-0-option.patch new file mode 100644 index 0000000..6727c9d --- /dev/null +++ b/SOURCES/0069-Fix-grub-probe-0-option.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Colin Watson +Date: Mon, 31 Mar 2014 13:51:17 +0100 +Subject: [PATCH] Fix grub-probe -0 option + +* util/grub-probe,c (options): Make -0 work again (broken by +conversion to argp). +(main): Simplify logic. +--- + util/grub-probe.c | 7 ++----- + ChangeLog | 6 ++++++ + 2 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/util/grub-probe.c b/util/grub-probe.c +index 1f3b59f05b9..80509be8aa7 100644 +--- a/util/grub-probe.c ++++ b/util/grub-probe.c +@@ -711,6 +711,7 @@ static struct argp_option options[] = { + N_("use FILE as the device map [default=%s]"), 0}, + {"target", 't', N_("TARGET"), 0, 0, 0}, + {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, ++ {0, '0', 0, 0, N_("separate items in output using ASCII NUL characters"), 0}, + { 0, 0, 0, 0, 0, 0 } + }; + +@@ -884,11 +885,7 @@ main (int argc, char *argv[]) + else + probe (arguments.devices[0], NULL, delim); + +- if (!arguments.zero_delim && (print == PRINT_BIOS_HINT +- || print == PRINT_IEEE1275_HINT +- || print == PRINT_BAREMETAL_HINT +- || print == PRINT_EFI_HINT +- || print == PRINT_ARC_HINT)) ++ if (delim == ' ') + putchar ('\n'); + + /* Free resources. */ +diff --git a/ChangeLog b/ChangeLog +index 9404edab8e1..efbed8ccbf6 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,9 @@ ++2014-03-31 Colin Watson ++ ++ * util/grub-probe,c (options): Make -0 work again (broken by ++ conversion to argp). ++ (main): Simplify logic. ++ + 2014-03-26 Vladimir Serbinenko + + * grub-core/lib/relocator.c: Fix the case when end of leftover is used. diff --git a/SOURCES/0070-Fix-partmap-cryptodisk-and-abstraction-handling-in-g.patch b/SOURCES/0070-Fix-partmap-cryptodisk-and-abstraction-handling-in-g.patch new file mode 100644 index 0000000..55939c1 --- /dev/null +++ b/SOURCES/0070-Fix-partmap-cryptodisk-and-abstraction-handling-in-g.patch @@ -0,0 +1,361 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Colin Watson +Date: Mon, 31 Mar 2014 14:48:33 +0100 +Subject: [PATCH] Fix partmap, cryptodisk, and abstraction handling in + grub-mkconfig. + +Commit 588744d0dc655177d5883bdcb8f72ff5160109ed caused grub-mkconfig +no longer to be forgiving of trailing spaces on grub-probe output +lines, which among other things means that util/grub.d/10_linux.in +no longer detects LVM. To fix this, make grub-probe's output +delimiting more consistent. As a bonus, this improves the coverage +of the -0 option. + +Fixes Debian bug #735935. + +* grub-core/disk/cryptodisk.c +(grub_util_cryptodisk_get_abstraction): Add a user-data argument. +* grub-core/disk/diskfilter.c (grub_diskfilter_get_partmap): +Likewise. +* include/grub/cryptodisk.h (grub_util_cryptodisk_get_abstraction): +Update prototype. +* include/grub/diskfilter.h (grub_diskfilter_get_partmap): Likewise. +* util/grub-install.c (push_partmap_module, push_cryptodisk_module, +probe_mods): Adjust for extra user-data arguments. +* util/grub-probe.c (do_print, probe_partmap, probe_cryptodisk_uuid, +probe_abstraction): Use configured delimiter. Update callers. +--- + grub-core/disk/cryptodisk.c | 19 ++++++++++--------- + grub-core/disk/diskfilter.c | 5 +++-- + util/grub-install.c | 14 ++++++++++---- + util/grub-probe.c | 46 ++++++++++++++++++++++----------------------- + include/grub/cryptodisk.h | 3 ++- + include/grub/diskfilter.h | 3 ++- + ChangeLog | 25 ++++++++++++++++++++++++ + 7 files changed, 74 insertions(+), 41 deletions(-) + +diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c +index 75c6e1f91ac..f0e3a900ae3 100644 +--- a/grub-core/disk/cryptodisk.c ++++ b/grub-core/disk/cryptodisk.c +@@ -762,25 +762,26 @@ grub_cryptodisk_cheat_insert (grub_cryptodisk_t newdev, const char *name, + + void + grub_util_cryptodisk_get_abstraction (grub_disk_t disk, +- void (*cb) (const char *val)) ++ void (*cb) (const char *val, void *data), ++ void *data) + { + grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data; + +- cb ("cryptodisk"); +- cb (dev->modname); ++ cb ("cryptodisk", data); ++ cb (dev->modname, data); + + if (dev->cipher) +- cb (dev->cipher->cipher->modname); ++ cb (dev->cipher->cipher->modname, data); + if (dev->secondary_cipher) +- cb (dev->secondary_cipher->cipher->modname); ++ cb (dev->secondary_cipher->cipher->modname, data); + if (dev->essiv_cipher) +- cb (dev->essiv_cipher->cipher->modname); ++ cb (dev->essiv_cipher->cipher->modname, data); + if (dev->hash) +- cb (dev->hash->modname); ++ cb (dev->hash->modname, data); + if (dev->essiv_hash) +- cb (dev->essiv_hash->modname); ++ cb (dev->essiv_hash->modname, data); + if (dev->iv_hash) +- cb (dev->iv_hash->modname); ++ cb (dev->iv_hash->modname, data); + } + + const char * +diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c +index 28b70c666d4..e8a3bcbd138 100644 +--- a/grub-core/disk/diskfilter.c ++++ b/grub-core/disk/diskfilter.c +@@ -354,7 +354,8 @@ grub_diskfilter_memberlist (grub_disk_t disk) + + void + grub_diskfilter_get_partmap (grub_disk_t disk, +- void (*cb) (const char *pm)) ++ void (*cb) (const char *pm, void *data), ++ void *data) + { + struct grub_diskfilter_lv *lv = disk->data; + struct grub_diskfilter_pv *pv; +@@ -376,7 +377,7 @@ grub_diskfilter_get_partmap (grub_disk_t disk, + continue; + } + for (s = 0; pv->partmaps[s]; s++) +- cb (pv->partmaps[s]); ++ cb (pv->partmaps[s], data); + } + } + +diff --git a/util/grub-install.c b/util/grub-install.c +index 2e6226a3716..e9c6a4656ef 100644 +--- a/util/grub-install.c ++++ b/util/grub-install.c +@@ -387,7 +387,7 @@ probe_raid_level (grub_disk_t disk) + } + + static void +-push_partmap_module (const char *map) ++push_partmap_module (const char *map, void *data __attribute__ ((unused))) + { + char buf[50]; + +@@ -401,6 +401,12 @@ push_partmap_module (const char *map) + grub_install_push_module (buf); + } + ++static void ++push_cryptodisk_module (const char *mod, void *data __attribute__ ((unused))) ++{ ++ grub_install_push_module (mod); ++} ++ + static void + probe_mods (grub_disk_t disk) + { +@@ -412,11 +418,11 @@ probe_mods (grub_disk_t disk) + grub_util_info ("no partition map found for %s", disk->name); + + for (part = disk->partition; part; part = part->parent) +- push_partmap_module (part->partmap->name); ++ push_partmap_module (part->partmap->name, NULL); + + if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID) + { +- grub_diskfilter_get_partmap (disk, push_partmap_module); ++ grub_diskfilter_get_partmap (disk, push_partmap_module, NULL); + have_abstractions = 1; + } + +@@ -432,7 +438,7 @@ probe_mods (grub_disk_t disk) + if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID) + { + grub_util_cryptodisk_get_abstraction (disk, +- grub_install_push_module); ++ push_cryptodisk_module, NULL); + have_abstractions = 1; + have_cryptodisk = 1; + } +diff --git a/util/grub-probe.c b/util/grub-probe.c +index 80509be8aa7..ecb7b6bbdf2 100644 +--- a/util/grub-probe.c ++++ b/util/grub-probe.c +@@ -130,13 +130,14 @@ get_targets_string (void) + } + + static void +-do_print (const char *x) ++do_print (const char *x, void *data) + { +- grub_printf ("%s ", x); ++ char delim = *(const char *) data; ++ grub_printf ("%s%c", x, delim); + } + + static void +-probe_partmap (grub_disk_t disk) ++probe_partmap (grub_disk_t disk, char delim) + { + grub_partition_t part; + grub_disk_memberlist_t list = NULL, tmp; +@@ -147,10 +148,10 @@ probe_partmap (grub_disk_t disk) + } + + for (part = disk->partition; part; part = part->parent) +- printf ("%s ", part->partmap->name); ++ printf ("%s%c", part->partmap->name, delim); + + if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID) +- grub_diskfilter_get_partmap (disk, do_print); ++ grub_diskfilter_get_partmap (disk, do_print, &delim); + + /* In case of LVM/RAID, check the member devices as well. */ + if (disk->dev->memberlist) +@@ -159,7 +160,7 @@ probe_partmap (grub_disk_t disk) + } + while (list) + { +- probe_partmap (list->disk); ++ probe_partmap (list->disk, delim); + tmp = list->next; + free (list); + list = tmp; +@@ -167,7 +168,7 @@ probe_partmap (grub_disk_t disk) + } + + static void +-probe_cryptodisk_uuid (grub_disk_t disk) ++probe_cryptodisk_uuid (grub_disk_t disk, char delim) + { + grub_disk_memberlist_t list = NULL, tmp; + +@@ -178,7 +179,7 @@ probe_cryptodisk_uuid (grub_disk_t disk) + } + while (list) + { +- probe_cryptodisk_uuid (list->disk); ++ probe_cryptodisk_uuid (list->disk, delim); + tmp = list->next; + free (list); + list = tmp; +@@ -186,7 +187,7 @@ probe_cryptodisk_uuid (grub_disk_t disk) + if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID) + { + const char *uu = grub_util_cryptodisk_get_uuid (disk); +- grub_printf ("%s ", uu); ++ grub_printf ("%s%c", uu, delim); + } + } + +@@ -210,7 +211,7 @@ probe_raid_level (grub_disk_t disk) + } + + static void +-probe_abstraction (grub_disk_t disk) ++probe_abstraction (grub_disk_t disk, char delim) + { + grub_disk_memberlist_t list = NULL, tmp; + int raid_level; +@@ -219,7 +220,7 @@ probe_abstraction (grub_disk_t disk) + list = disk->dev->memberlist (disk); + while (list) + { +- probe_abstraction (list->disk); ++ probe_abstraction (list->disk, delim); + + tmp = list->next; + free (list); +@@ -229,26 +230,26 @@ probe_abstraction (grub_disk_t disk) + if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID + && (grub_memcmp (disk->name, "lvm/", sizeof ("lvm/") - 1) == 0 || + grub_memcmp (disk->name, "lvmid/", sizeof ("lvmid/") - 1) == 0)) +- printf ("lvm "); ++ printf ("lvm%c", delim); + + if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID + && grub_memcmp (disk->name, "ldm/", sizeof ("ldm/") - 1) == 0) +- printf ("ldm "); ++ printf ("ldm%c", delim); + + if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID) +- grub_util_cryptodisk_get_abstraction (disk, do_print); ++ grub_util_cryptodisk_get_abstraction (disk, do_print, &delim); + + raid_level = probe_raid_level (disk); + if (raid_level >= 0) + { +- printf ("diskfilter "); ++ printf ("diskfilter%c", delim); + if (disk->dev->raidname) +- printf ("%s ", disk->dev->raidname (disk)); ++ printf ("%s%c", disk->dev->raidname (disk), delim); + } + if (raid_level == 5) +- printf ("raid5rec "); ++ printf ("raid5rec%c", delim); + if (raid_level == 6) +- printf ("raid6rec "); ++ printf ("raid6rec%c", delim); + } + + static void +@@ -630,16 +631,14 @@ probe (const char *path, char **device_names, char delim) + + if (print == PRINT_ABSTRACTION) + { +- probe_abstraction (dev->disk); +- putchar (delim); ++ probe_abstraction (dev->disk, delim); + grub_device_close (dev); + continue; + } + + if (print == PRINT_CRYPTODISK_UUID) + { +- probe_cryptodisk_uuid (dev->disk); +- putchar (delim); ++ probe_cryptodisk_uuid (dev->disk, delim); + grub_device_close (dev); + continue; + } +@@ -647,8 +646,7 @@ probe (const char *path, char **device_names, char delim) + if (print == PRINT_PARTMAP) + { + /* Check if dev->disk itself is contained in a partmap. */ +- probe_partmap (dev->disk); +- putchar (delim); ++ probe_partmap (dev->disk, delim); + grub_device_close (dev); + continue; + } +diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h +index 66f3e1e221b..f2ad2a79ab2 100644 +--- a/include/grub/cryptodisk.h ++++ b/include/grub/cryptodisk.h +@@ -145,7 +145,8 @@ grub_cryptodisk_cheat_insert (grub_cryptodisk_t newdev, const char *name, + grub_disk_t source, const char *cheat); + void + grub_util_cryptodisk_get_abstraction (grub_disk_t disk, +- void (*cb) (const char *val)); ++ void (*cb) (const char *val, void *data), ++ void *data); + + char * + grub_util_get_geli_uuid (const char *dev); +diff --git a/include/grub/diskfilter.h b/include/grub/diskfilter.h +index 042fe04a5a4..1aedcd3dffb 100644 +--- a/include/grub/diskfilter.h ++++ b/include/grub/diskfilter.h +@@ -202,7 +202,8 @@ grub_diskfilter_get_pv_from_disk (grub_disk_t disk, + struct grub_diskfilter_vg **vg); + void + grub_diskfilter_get_partmap (grub_disk_t disk, +- void (*cb) (const char *val)); ++ void (*cb) (const char *val, void *data), ++ void *data); + #endif + + #endif /* ! GRUB_RAID_H */ +diff --git a/ChangeLog b/ChangeLog +index efbed8ccbf6..1cb3b683fcf 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,28 @@ ++2014-03-31 Colin Watson ++ ++ Fix partmap, cryptodisk, and abstraction handling in grub-mkconfig. ++ ++ Commit 588744d0dc655177d5883bdcb8f72ff5160109ed caused grub-mkconfig ++ no longer to be forgiving of trailing spaces on grub-probe output ++ lines, which among other things means that util/grub.d/10_linux.in ++ no longer detects LVM. To fix this, make grub-probe's output ++ delimiting more consistent. As a bonus, this improves the coverage ++ of the -0 option. ++ ++ Fixes Debian bug #735935. ++ ++ * grub-core/disk/cryptodisk.c ++ (grub_util_cryptodisk_get_abstraction): Add a user-data argument. ++ * grub-core/disk/diskfilter.c (grub_diskfilter_get_partmap): ++ Likewise. ++ * include/grub/cryptodisk.h (grub_util_cryptodisk_get_abstraction): ++ Update prototype. ++ * include/grub/diskfilter.h (grub_diskfilter_get_partmap): Likewise. ++ * util/grub-install.c (push_partmap_module, push_cryptodisk_module, ++ probe_mods): Adjust for extra user-data arguments. ++ * util/grub-probe.c (do_print, probe_partmap, probe_cryptodisk_uuid, ++ probe_abstraction): Use configured delimiter. Update callers. ++ + 2014-03-31 Colin Watson + + * util/grub-probe,c (options): Make -0 work again (broken by diff --git a/SOURCES/0071-btrfs-fix-get_root-key-comparison-failures-due-to-en.patch b/SOURCES/0071-btrfs-fix-get_root-key-comparison-failures-due-to-en.patch new file mode 100644 index 0000000..9d091a0 --- /dev/null +++ b/SOURCES/0071-btrfs-fix-get_root-key-comparison-failures-due-to-en.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thomas Falcon +Date: Mon, 31 Mar 2014 15:32:30 +0100 +Subject: [PATCH] btrfs: fix get_root key comparison failures due to endianness + +* grub-core/fs/btrfs.c (get_root): Convert +GRUB_BTRFS_ROOT_VOL_OBJECTID to little-endian. +--- + grub-core/fs/btrfs.c | 2 +- + ChangeLog | 7 +++++++ + 2 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c +index 89666b6fd59..f7b6c152037 100644 +--- a/grub-core/fs/btrfs.c ++++ b/grub-core/fs/btrfs.c +@@ -1201,7 +1201,7 @@ get_root (struct grub_btrfs_data *data, struct grub_btrfs_key *key, + struct grub_btrfs_key key_out, key_in; + struct grub_btrfs_root_item ri; + +- key_in.object_id = GRUB_BTRFS_ROOT_VOL_OBJECTID; ++ key_in.object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_ROOT_VOL_OBJECTID); + key_in.offset = 0; + key_in.type = GRUB_BTRFS_ITEM_TYPE_ROOT_ITEM; + err = lower_bound (data, &key_in, &key_out, +diff --git a/ChangeLog b/ChangeLog +index 1cb3b683fcf..accffade86b 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,10 @@ ++2014-03-31 Thomas Falcon ++ ++ btrfs: fix get_root key comparison failures due to endianness ++ ++ * grub-core/fs/btrfs.c (get_root): Convert ++ GRUB_BTRFS_ROOT_VOL_OBJECTID to little-endian. ++ + 2014-03-31 Colin Watson + + Fix partmap, cryptodisk, and abstraction handling in grub-mkconfig. diff --git a/SOURCES/0072-grub-core-osdep-linux-getroot.c-grub_util_part_to_di.patch b/SOURCES/0072-grub-core-osdep-linux-getroot.c-grub_util_part_to_di.patch new file mode 100644 index 0000000..c98e586 --- /dev/null +++ b/SOURCES/0072-grub-core-osdep-linux-getroot.c-grub_util_part_to_di.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Thu, 3 Apr 2014 21:31:12 +0200 +Subject: [PATCH] * grub-core/osdep/linux/getroot.c (grub_util_part_to_disk): + Support NVMe device names. + +--- + grub-core/osdep/linux/getroot.c | 17 +++++++++++++++++ + ChangeLog | 5 +++++ + 2 files changed, 22 insertions(+) + +diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c +index 19581d32997..7007193d9c7 100644 +--- a/grub-core/osdep/linux/getroot.c ++++ b/grub-core/osdep/linux/getroot.c +@@ -896,6 +896,23 @@ grub_util_part_to_disk (const char *os_dev, struct stat *st, + *pp = '\0'; + return path; + } ++ ++ /* If this is a NVMe device */ ++ if ((strncmp ("nvme", p, 4) == 0) && p[4] >= '0' && p[4] <= '9') ++ { ++ char *pp = p + 4; ++ while (*pp >= '0' && *pp <= '9') ++ pp++; ++ if (*pp == 'n') ++ pp++; ++ while (*pp >= '0' && *pp <= '9') ++ pp++; ++ if (*pp == 'p') ++ *is_part = 1; ++ /* /dev/nvme[0-9]+n[0-9]+p[0-9]* */ ++ *pp = '\0'; ++ return path; ++ } + } + + return path; +diff --git a/ChangeLog b/ChangeLog +index accffade86b..4a484092a6f 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2014-04-03 Vladimir Serbinenko ++ ++ * grub-core/osdep/linux/getroot.c (grub_util_part_to_disk): Support NVMe ++ device names. ++ + 2014-03-31 Thomas Falcon + + btrfs: fix get_root key comparison failures due to endianness diff --git a/SOURCES/0073-Replace-few-instances-of-memcmp-memcpy-in-the-code-t.patch b/SOURCES/0073-Replace-few-instances-of-memcmp-memcpy-in-the-code-t.patch new file mode 100644 index 0000000..3627cff --- /dev/null +++ b/SOURCES/0073-Replace-few-instances-of-memcmp-memcpy-in-the-code-t.patch @@ -0,0 +1,99 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Fri, 4 Apr 2014 07:58:42 +0200 +Subject: [PATCH] Replace few instances of memcmp/memcpy in the code that + should be grub_memcmp/grub_memcpy. + +--- + grub-core/commands/acpihalt.c | 4 ++-- + grub-core/commands/legacycfg.c | 4 ++-- + grub-core/lib/relocator.c | 2 +- + grub-core/loader/i386/bsd.c | 4 ++-- + ChangeLog | 5 +++++ + 5 files changed, 12 insertions(+), 7 deletions(-) + +diff --git a/grub-core/commands/acpihalt.c b/grub-core/commands/acpihalt.c +index 09421a6c69d..83bdfe1f23c 100644 +--- a/grub-core/commands/acpihalt.c ++++ b/grub-core/commands/acpihalt.c +@@ -214,8 +214,8 @@ get_sleep_type (grub_uint8_t *table, grub_uint8_t *ptr, grub_uint8_t *end, + } + case GRUB_ACPI_OPCODE_NAME: + ptr++; +- if ((!scope || memcmp (scope, "\\", scope_len) == 0) && +- (memcmp (ptr, "_S5_", 4) == 0 || memcmp (ptr, "\\_S5_", 4) == 0)) ++ if ((!scope || grub_memcmp (scope, "\\", scope_len) == 0) && ++ (grub_memcmp (ptr, "_S5_", 4) == 0 || grub_memcmp (ptr, "\\_S5_", 4) == 0)) + { + int ll; + grub_uint8_t *ptr2 = ptr; +diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c +index e42a9d83ebb..2c09fb7dd78 100644 +--- a/grub-core/commands/legacycfg.c ++++ b/grub-core/commands/legacycfg.c +@@ -580,7 +580,7 @@ check_password_md5_real (const char *entered, + GRUB_MD_MD5->write (ctx, entered, enteredlen); + digest = GRUB_MD_MD5->read (ctx); + GRUB_MD_MD5->final (ctx); +- memcpy (alt_result, digest, MD5_HASHLEN); ++ grub_memcpy (alt_result, digest, MD5_HASHLEN); + + GRUB_MD_MD5->init (ctx); + GRUB_MD_MD5->write (ctx, entered, enteredlen); +@@ -596,7 +596,7 @@ check_password_md5_real (const char *entered, + + for (i = 0; i < 1000; i++) + { +- memcpy (alt_result, digest, 16); ++ grub_memcpy (alt_result, digest, 16); + + GRUB_MD_MD5->init (ctx); + if ((i & 1) != 0) +diff --git a/grub-core/lib/relocator.c b/grub-core/lib/relocator.c +index cb11ea5fa27..f759c7f41f4 100644 +--- a/grub-core/lib/relocator.c ++++ b/grub-core/lib/relocator.c +@@ -652,7 +652,7 @@ malloc_in_range (struct grub_relocator *rel, + for (i = 0; i < (BITS_IN_BYTE * sizeof (grub_addr_t) / DIGITSORT_BITS); + i++) + { +- memset (counter, 0, (1 + (1 << DIGITSORT_BITS)) * sizeof (counter[0])); ++ grub_memset (counter, 0, (1 + (1 << DIGITSORT_BITS)) * sizeof (counter[0])); + for (j = 0; j < N; j++) + counter[((events[j].pos >> (DIGITSORT_BITS * i)) + & DIGITSORT_MASK) + 1]++; +diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c +index 19985f03e65..41ef9109ee1 100644 +--- a/grub-core/loader/i386/bsd.c ++++ b/grub-core/loader/i386/bsd.c +@@ -1082,7 +1082,7 @@ grub_netbsd_add_boot_disk_and_wedge (void) + + grub_crypto_hash (GRUB_MD_MD5, hash, + buf.raw, GRUB_DISK_SECTOR_SIZE); +- memcpy (biw.matchhash, hash, 16); ++ grub_memcpy (biw.matchhash, hash, 16); + + grub_bsd_add_meta (NETBSD_BTINFO_BOOTWEDGE, &biw, sizeof (biw)); + } +@@ -1100,7 +1100,7 @@ grub_netbsd_add_boot_disk_and_wedge (void) + bid.labelsector = partmapsector; + bid.label.type = buf.label.type; + bid.label.checksum = buf.label.checksum; +- memcpy (bid.label.packname, buf.label.packname, 16); ++ grub_memcpy (bid.label.packname, buf.label.packname, 16); + } + else + { +diff --git a/ChangeLog b/ChangeLog +index 4a484092a6f..f18cdba90ce 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2014-04-04 Vladimir Serbinenko ++ ++ Replace few instances of memcmp/memcpy in the code that should be ++ grub_memcmp/grub_memcpy. ++ + 2014-04-03 Vladimir Serbinenko + + * grub-core/osdep/linux/getroot.c (grub_util_part_to_disk): Support NVMe diff --git a/SOURCES/0074-include-grub-libgcc.h-Remove-ctzsi2-and-ctzdi2.-They.patch b/SOURCES/0074-include-grub-libgcc.h-Remove-ctzsi2-and-ctzdi2.-They.patch new file mode 100644 index 0000000..fce04da --- /dev/null +++ b/SOURCES/0074-include-grub-libgcc.h-Remove-ctzsi2-and-ctzdi2.-They.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Fri, 4 Apr 2014 08:02:38 +0200 +Subject: [PATCH] * include/grub/libgcc.h: Remove ctzsi2 and ctzdi2. They're no + longer pulled from libgcc. + +--- + include/grub/libgcc.h | 7 ------- + ChangeLog | 5 +++++ + 2 files changed, 5 insertions(+), 7 deletions(-) + +diff --git a/include/grub/libgcc.h b/include/grub/libgcc.h +index fdc6611a04c..97233d79e4c 100644 +--- a/include/grub/libgcc.h ++++ b/include/grub/libgcc.h +@@ -42,13 +42,6 @@ void EXPORT_FUNC (__bswapsi2) (void); + # ifdef HAVE___BSWAPDI2 + void EXPORT_FUNC (__bswapdi2) (void); + # endif +-# ifdef HAVE___CTZDI2 +-void EXPORT_FUNC (__ctzdi2) (void); +-# endif +-# ifdef HAVE___CTZSI2 +-void EXPORT_FUNC (__ctzsi2) (void); +-# endif +-#endif + + #ifdef HAVE__RESTGPR_14_X + void EXPORT_FUNC (_restgpr_14_x) (void); +diff --git a/ChangeLog b/ChangeLog +index f18cdba90ce..90e41bdadb3 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2014-04-04 Vladimir Serbinenko ++ ++ * include/grub/libgcc.h: Remove ctzsi2 and ctzdi2. They're no longer ++ pulled from libgcc. ++ + 2014-04-04 Vladimir Serbinenko + + Replace few instances of memcmp/memcpy in the code that should be diff --git a/SOURCES/0075-Add-missing-endif.patch b/SOURCES/0075-Add-missing-endif.patch new file mode 100644 index 0000000..f2a1037 --- /dev/null +++ b/SOURCES/0075-Add-missing-endif.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Fri, 4 Apr 2014 08:11:15 +0200 +Subject: [PATCH] Add missing #endif + +--- + include/grub/libgcc.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/grub/libgcc.h b/include/grub/libgcc.h +index 97233d79e4c..8e93b6792d9 100644 +--- a/include/grub/libgcc.h ++++ b/include/grub/libgcc.h +@@ -42,6 +42,7 @@ void EXPORT_FUNC (__bswapsi2) (void); + # ifdef HAVE___BSWAPDI2 + void EXPORT_FUNC (__bswapdi2) (void); + # endif ++#endif + + #ifdef HAVE__RESTGPR_14_X + void EXPORT_FUNC (_restgpr_14_x) (void); diff --git a/SOURCES/0076-grub-core-lib-syslinux_parse.c-Fix-timeout-quoting.patch b/SOURCES/0076-grub-core-lib-syslinux_parse.c-Fix-timeout-quoting.patch new file mode 100644 index 0000000..b738f38 --- /dev/null +++ b/SOURCES/0076-grub-core-lib-syslinux_parse.c-Fix-timeout-quoting.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Sun, 6 Apr 2014 00:44:44 +0200 +Subject: [PATCH] * grub-core/lib/syslinux_parse.c: Fix timeout quoting. + +--- + grub-core/lib/syslinux_parse.c | 2 +- + ChangeLog | 4 ++++ + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/grub-core/lib/syslinux_parse.c b/grub-core/lib/syslinux_parse.c +index 21fa17504aa..6bc504b7c58 100644 +--- a/grub-core/lib/syslinux_parse.c ++++ b/grub-core/lib/syslinux_parse.c +@@ -1432,7 +1432,7 @@ config_file (struct output_buffer *outbuf, + for (curentry = menu.entries; curentry->next; curentry = curentry->next); + lentry = curentry; + +- print_string ("set timeout='"); ++ print_string ("set timeout="); + err = print_num (outbuf, (menu.timeout + 9) / 10); + if (err) + return err; +diff --git a/ChangeLog b/ChangeLog +index 90e41bdadb3..50d9291624a 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2014-04-06 Vladimir Serbinenko ++ ++ * grub-core/lib/syslinux_parse.c: Fix timeout quoting. ++ + 2014-04-04 Vladimir Serbinenko + + * include/grub/libgcc.h: Remove ctzsi2 and ctzdi2. They're no longer diff --git a/SOURCES/0077-Improve-LVM-logical_volumes-string-matching.patch b/SOURCES/0077-Improve-LVM-logical_volumes-string-matching.patch new file mode 100644 index 0000000..c5c603d --- /dev/null +++ b/SOURCES/0077-Improve-LVM-logical_volumes-string-matching.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Colin Watson +Date: Thu, 10 Apr 2014 14:42:41 +0100 +Subject: [PATCH] Improve LVM "logical_volumes" string matching + +* grub-core/disk/lvm.c (grub_lvm_detect): Search for +"logical_volumes" block a little more accurately. +--- + grub-core/disk/lvm.c | 4 ++-- + ChangeLog | 5 +++++ + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c +index 483c17eb5f6..862a9664f2c 100644 +--- a/grub-core/disk/lvm.c ++++ b/grub-core/disk/lvm.c +@@ -333,10 +333,10 @@ grub_lvm_detect (grub_disk_t disk, + } + } + +- p = grub_strstr (p, "logical_volumes"); ++ p = grub_strstr (p, "logical_volumes {"); + if (p) + { +- p += sizeof ("logical_volumes = ") - 1; ++ p += sizeof ("logical_volumes {") - 1; + + /* And add all the lvs to the volume group. */ + while (1) +diff --git a/ChangeLog b/ChangeLog +index 50d9291624a..7f0c57dc0ae 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2014-04-10 Colin Watson ++ ++ * grub-core/disk/lvm.c (grub_lvm_detect): Search for ++ "logical_volumes" block a little more accurately. ++ + 2014-04-06 Vladimir Serbinenko + + * grub-core/lib/syslinux_parse.c: Fix timeout quoting. diff --git a/SOURCES/0078-Tolerate-devices-with-no-filesystem-UUID-returned-by.patch b/SOURCES/0078-Tolerate-devices-with-no-filesystem-UUID-returned-by.patch new file mode 100644 index 0000000..1633534 --- /dev/null +++ b/SOURCES/0078-Tolerate-devices-with-no-filesystem-UUID-returned-by.patch @@ -0,0 +1,78 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Colin Watson +Date: Thu, 10 Apr 2014 16:54:33 +0100 +Subject: [PATCH] Tolerate devices with no filesystem UUID returned by + os-prober + +* util/grub.d/30_os-prober.in: Tolerate devices with no filesystem +UUID. Other parts of grub-mkconfig tolerate these, they were +previously allowed here up to commit +55e706c918922def17f5012c23cfe88c4c645208, and they can arise in +practice when the system has active LVM snapshots. +Fixes Ubuntu bug #1287436. +--- + ChangeLog | 9 +++++++++ + util/grub.d/30_os-prober.in | 23 +++++++++++++---------- + 2 files changed, 22 insertions(+), 10 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index 7f0c57dc0ae..35564681a4d 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,12 @@ ++2014-04-10 Colin Watson ++ ++ * util/grub.d/30_os-prober.in: Tolerate devices with no filesystem ++ UUID. Other parts of grub-mkconfig tolerate these, they were ++ previously allowed here up to commit ++ 55e706c918922def17f5012c23cfe88c4c645208, and they can arise in ++ practice when the system has active LVM snapshots. ++ Fixes Ubuntu bug #1287436. ++ + 2014-04-10 Colin Watson + + * grub-core/disk/lvm.c (grub_lvm_detect): Search for +diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in +index 7cf8487d63a..6f38c82a554 100644 +--- a/util/grub.d/30_os-prober.in ++++ b/util/grub.d/30_os-prober.in +@@ -112,16 +112,17 @@ for OS in ${OSPROBED} ; do + LONGNAME="`echo ${OS} | cut -d ':' -f 2 | tr '^' ' '`" + LABEL="`echo ${OS} | cut -d ':' -f 3 | tr '^' ' '`" + BOOT="`echo ${OS} | cut -d ':' -f 4`" +- UUID="`${grub_probe} --target=fs_uuid --device ${DEVICE%@*}`" +- EXPUUID="$UUID" ++ if UUID="`${grub_probe} --target=fs_uuid --device ${DEVICE%@*}`"; then ++ EXPUUID="$UUID" + +- if [ x"${DEVICE#*@}" != x ] ; then ++ if [ x"${DEVICE#*@}" != x ] ; then + EXPUUID="${EXPUUID}@${DEVICE#*@}" +- fi ++ fi + +- if [ "x${GRUB_OS_PROBER_SKIP_LIST}" != "x" ] && [ "x`echo ${GRUB_OS_PROBER_SKIP_LIST} | grep -i -e '\b'${EXPUUID}'\b'`" != "x" ] ; then +- echo "Skipped ${LONGNAME} on ${DEVICE} by user request." >&2 +- continue ++ if [ "x${GRUB_OS_PROBER_SKIP_LIST}" != "x" ] && [ "x`echo ${GRUB_OS_PROBER_SKIP_LIST} | grep -i -e '\b'${EXPUUID}'\b'`" != "x" ] ; then ++ echo "Skipped ${LONGNAME} on ${DEVICE} by user request." >&2 ++ continue ++ fi + fi + + BTRFS="`echo ${OS} | cut -d ':' -f 5`" +@@ -277,9 +278,11 @@ EOF + echo "$title_correction_code" + ;; + macosx) +- OSXUUID="${UUID}" +- osx_entry xnu_kernel 32 +- osx_entry xnu_kernel64 64 ++ if [ "${UUID}" ]; then ++ OSXUUID="${UUID}" ++ osx_entry xnu_kernel 32 ++ osx_entry xnu_kernel64 64 ++ fi + ;; + hurd) + onstr="$(gettext_printf "(on %s)" "${DEVICE}")" diff --git a/SOURCES/0079-Allow-loading-old-kernels-by-placing-GDT-in-conventi.patch b/SOURCES/0079-Allow-loading-old-kernels-by-placing-GDT-in-conventi.patch new file mode 100644 index 0000000..bb34f1c --- /dev/null +++ b/SOURCES/0079-Allow-loading-old-kernels-by-placing-GDT-in-conventi.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Piotr Krysiuk +Date: Sun, 20 Apr 2014 15:58:45 +0200 +Subject: [PATCH] Allow loading old kernels by placing GDT in conventional + memory. + +--- + grub-core/lib/i386/relocator.c | 11 +++++++---- + ChangeLog | 5 +++++ + 2 files changed, 12 insertions(+), 4 deletions(-) + +diff --git a/grub-core/lib/i386/relocator.c b/grub-core/lib/i386/relocator.c +index d2a1b27ae0e..ffaf25f088d 100644 +--- a/grub-core/lib/i386/relocator.c ++++ b/grub-core/lib/i386/relocator.c +@@ -81,10 +81,13 @@ grub_relocator32_boot (struct grub_relocator *rel, + void *relst; + grub_relocator_chunk_t ch; + +- err = grub_relocator_alloc_chunk_align (rel, &ch, 0, +- (0xffffffff - RELOCATOR_SIZEOF (32)) +- + 1, RELOCATOR_SIZEOF (32), 16, +- GRUB_RELOCATOR_PREFERENCE_NONE, ++ /* Specific memory range due to Global Descriptor Table for use by payload ++ that we will store in returned chunk. The address range and preference ++ are based on "THE LINUX/x86 BOOT PROTOCOL" specification. */ ++ err = grub_relocator_alloc_chunk_align (rel, &ch, 0x1000, ++ 0x9a000 - RELOCATOR_SIZEOF (32), ++ RELOCATOR_SIZEOF (32), 16, ++ GRUB_RELOCATOR_PREFERENCE_LOW, + avoid_efi_bootservices); + if (err) + return err; +diff --git a/ChangeLog b/ChangeLog +index 35564681a4d..73a89289945 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2014-04-20 Piotr Krysiuk ++ ++ * grub-core/lib/i386/relocator.c: Allow loading old kernels by placing ++ GDT in conventional memory. ++ + 2014-04-10 Colin Watson + + * util/grub.d/30_os-prober.in: Tolerate devices with no filesystem diff --git a/SOURCES/0080-grub-core-kern-misc.c-__bzero-Don-t-compile-in-GRUB_.patch b/SOURCES/0080-grub-core-kern-misc.c-__bzero-Don-t-compile-in-GRUB_.patch new file mode 100644 index 0000000..3aeb75c --- /dev/null +++ b/SOURCES/0080-grub-core-kern-misc.c-__bzero-Don-t-compile-in-GRUB_.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Sun, 20 Apr 2014 16:12:41 +0200 +Subject: [PATCH] * grub-core/kern/misc.c (__bzero): Don't compile in + GRUB_UTIL. + + Reported by: Yves Blusseau . +--- + grub-core/kern/misc.c | 3 +++ + ChangeLog | 6 ++++++ + 2 files changed, 9 insertions(+) + +diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c +index 54db2e1254e..c5c815d8d13 100644 +--- a/grub-core/kern/misc.c ++++ b/grub-core/kern/misc.c +@@ -542,6 +542,9 @@ memset (void *s, int c, grub_size_t n) + return grub_memset (s, c, n); + } + ++#endif ++ ++#if !defined(GRUB_UTIL) && defined(__APPLE__) + void GRUB_BUILTIN_ATTR + __bzero (void *s, grub_size_t n) + { +diff --git a/ChangeLog b/ChangeLog +index 73a89289945..3b61c0a996d 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,9 @@ ++2014-04-20 Vladimir Serbinenko ++ ++ * grub-core/kern/misc.c (__bzero): Don't compile in GRUB_UTIL. ++ ++ Reported by: Yves Blusseau . ++ + 2014-04-20 Piotr Krysiuk + + * grub-core/lib/i386/relocator.c: Allow loading old kernels by placing diff --git a/SOURCES/0081-grub-core-commands-verify.c-grub_pubkey_open-Fix-mem.patch b/SOURCES/0081-grub-core-commands-verify.c-grub_pubkey_open-Fix-mem.patch new file mode 100644 index 0000000..f941491 --- /dev/null +++ b/SOURCES/0081-grub-core-commands-verify.c-grub_pubkey_open-Fix-mem.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Mon, 12 May 2014 10:01:48 +0200 +Subject: [PATCH] * grub-core/commands/verify.c (grub_pubkey_open): Fix memdisk + check. + +--- + grub-core/commands/verify.c | 2 +- + ChangeLog | 5 +++++ + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/grub-core/commands/verify.c b/grub-core/commands/verify.c +index a9dfd885247..6349ccfbaea 100644 +--- a/grub-core/commands/verify.c ++++ b/grub-core/commands/verify.c +@@ -835,7 +835,7 @@ grub_pubkey_open (grub_file_t io, const char *filename) + + if (!sec) + return io; +- if (io->device->disk && io->device->disk->id == GRUB_DISK_DEVICE_MEMDISK_ID) ++ if (io->device->disk && io->device->disk->dev->id == GRUB_DISK_DEVICE_MEMDISK_ID) + return io; + fsuf = grub_malloc (grub_strlen (filename) + sizeof (".sig")); + if (!fsuf) +diff --git a/ChangeLog b/ChangeLog +index 3b61c0a996d..d0896d89e53 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2014-06-21 Vladimir Serbinenko ++ ++ * grub-core/commands/verify.c (grub_pubkey_open): Fix memdisk ++ check. ++ + 2014-04-20 Vladimir Serbinenko + + * grub-core/kern/misc.c (__bzero): Don't compile in GRUB_UTIL. diff --git a/SOURCES/0082-grub-core-commands-verify.c-grub_pubkey_open-Trust-p.patch b/SOURCES/0082-grub-core-commands-verify.c-grub_pubkey_open-Trust-p.patch new file mode 100644 index 0000000..c86aea0 --- /dev/null +++ b/SOURCES/0082-grub-core-commands-verify.c-grub_pubkey_open-Trust-p.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Thu, 15 May 2014 14:36:48 +0200 +Subject: [PATCH] * grub-core/commands/verify.c (grub_pubkey_open): Trust + procfs. + +--- + grub-core/commands/verify.c | 4 +++- + ChangeLog | 4 ++++ + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/grub-core/commands/verify.c b/grub-core/commands/verify.c +index 6349ccfbaea..525bdd18737 100644 +--- a/grub-core/commands/verify.c ++++ b/grub-core/commands/verify.c +@@ -835,7 +835,9 @@ grub_pubkey_open (grub_file_t io, const char *filename) + + if (!sec) + return io; +- if (io->device->disk && io->device->disk->dev->id == GRUB_DISK_DEVICE_MEMDISK_ID) ++ if (io->device->disk && ++ (io->device->disk->dev->id == GRUB_DISK_DEVICE_MEMDISK_ID ++ || io->device->disk->dev->id == GRUB_DISK_DEVICE_PROCFS_ID)) + return io; + fsuf = grub_malloc (grub_strlen (filename) + sizeof (".sig")); + if (!fsuf) +diff --git a/ChangeLog b/ChangeLog +index d0896d89e53..2a94ad979b3 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2014-06-21 Vladimir Serbinenko ++ ++ * grub-core/commands/verify.c (grub_pubkey_open): Trust procfs. ++ + 2014-06-21 Vladimir Serbinenko + + * grub-core/commands/verify.c (grub_pubkey_open): Fix memdisk diff --git a/SOURCES/0083-util-grub-gen-asciih.c-add_glyph-Fix-uninitialised-v.patch b/SOURCES/0083-util-grub-gen-asciih.c-add_glyph-Fix-uninitialised-v.patch new file mode 100644 index 0000000..3933381 --- /dev/null +++ b/SOURCES/0083-util-grub-gen-asciih.c-add_glyph-Fix-uninitialised-v.patch @@ -0,0 +1,70 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Trevor Woerner +Date: Sat, 21 Jun 2014 20:26:47 +0200 +Subject: [PATCH] * util/grub-gen-asciih.c (add_glyph): Fix uninitialised + variable. + +--- + util/grub-gen-asciih.c | 15 +++++++++------ + ChangeLog | 4 ++++ + 2 files changed, 13 insertions(+), 6 deletions(-) + +diff --git a/util/grub-gen-asciih.c b/util/grub-gen-asciih.c +index e01447ae94f..e35dcb78fe6 100644 +--- a/util/grub-gen-asciih.c ++++ b/util/grub-gen-asciih.c +@@ -81,14 +81,14 @@ add_glyph (FT_UInt glyph_idx, FT_Face face, + err = FT_Load_Glyph (face, glyph_idx, flag); + if (err) + { +- printf ("Freetype Error %d loading glyph 0x%x for U+0x%x", ++ fprintf (stderr, "Freetype Error %d loading glyph 0x%x for U+0x%x", + err, glyph_idx, char_code); + + if (err > 0 && err < (signed) ARRAY_SIZE (ft_errmsgs)) +- printf (": %s\n", ft_errmsgs[err]); ++ fprintf (stderr, ": %s\n", ft_errmsgs[err]); + else +- printf ("\n"); +- return; ++ fprintf (stderr, "\n"); ++ exit (1); + } + + glyph = face->glyph; +@@ -128,7 +128,6 @@ add_glyph (FT_UInt glyph_idx, FT_Face face, + static void + write_font_ascii_bitmap (FILE *file, FT_Face face) + { +- struct grub_glyph_info glyph; + int char_code; + + fprintf (file, "/* THIS CHUNK OF BYTES IS AUTOMATICALLY GENERATED */\n"); +@@ -138,10 +137,14 @@ write_font_ascii_bitmap (FILE *file, FT_Face face) + for (char_code = 0; char_code <= 0x7f; char_code++) + { + FT_UInt glyph_idx; +- ++ struct grub_glyph_info glyph; ++ + glyph_idx = FT_Get_Char_Index (face, char_code); + if (!glyph_idx) + return; ++ ++ memset (&glyph, 0, sizeof(glyph)); ++ + add_glyph (glyph_idx, face, char_code, &glyph); + + if (glyph.width == 8 && glyph.height == 16 +diff --git a/ChangeLog b/ChangeLog +index 2a94ad979b3..b5521130874 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2014-06-21 Trevor Woerner ++ ++ * util/grub-gen-asciih.c (add_glyph): Fix uninitialised variable. ++ + 2014-06-21 Vladimir Serbinenko + + * grub-core/commands/verify.c (grub_pubkey_open): Trust procfs. diff --git a/SOURCES/0084-grub-core-commands-efi-lsefisystab.c-grub_cmd_lsefis.patch b/SOURCES/0084-grub-core-commands-efi-lsefisystab.c-grub_cmd_lsefis.patch new file mode 100644 index 0000000..1a1d5f7 --- /dev/null +++ b/SOURCES/0084-grub-core-commands-efi-lsefisystab.c-grub_cmd_lsefis.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Stephane Rochoy +Date: Sun, 22 Jun 2014 01:34:57 +0200 +Subject: [PATCH] * grub-core/commands/efi/lsefisystab.c + (grub_cmd_lsefisystab): Show EFI system table physical address. + +--- + grub-core/commands/efi/lsefisystab.c | 1 + + ChangeLog | 5 +++++ + 2 files changed, 6 insertions(+) + +diff --git a/grub-core/commands/efi/lsefisystab.c b/grub-core/commands/efi/lsefisystab.c +index eda8c5ff3f3..8717db91ea2 100644 +--- a/grub-core/commands/efi/lsefisystab.c ++++ b/grub-core/commands/efi/lsefisystab.c +@@ -52,6 +52,7 @@ grub_cmd_lsefisystab (struct grub_command *cmd __attribute__ ((unused)), + grub_efi_configuration_table_t *t; + unsigned int i; + ++ grub_printf ("Address: %p\n", st); + grub_printf ("Signature: %016" PRIxGRUB_UINT64_T " revision: %08x\n", + st->hdr.signature, st->hdr.revision); + { +diff --git a/ChangeLog b/ChangeLog +index b5521130874..abf8f4b2716 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2014-06-21 Stephane Rochoy ++ ++ * grub-core/commands/efi/lsefisystab.c (grub_cmd_lsefisystab): Show ++ EFI system table physical address. ++ + 2014-06-21 Trevor Woerner + + * util/grub-gen-asciih.c (add_glyph): Fix uninitialised variable. diff --git a/SOURCES/0085-grub-core-loader-i386-bsd.c-grub_netbsd_boot-Pass-po.patch b/SOURCES/0085-grub-core-loader-i386-bsd.c-grub_netbsd_boot-Pass-po.patch new file mode 100644 index 0000000..bfb63cc --- /dev/null +++ b/SOURCES/0085-grub-core-loader-i386-bsd.c-grub_netbsd_boot-Pass-po.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Stephane Rochoy +Date: Sun, 22 Jun 2014 01:35:52 +0200 +Subject: [PATCH] * grub-core/loader/i386/bsd.c (grub_netbsd_boot): Pass + pointer to EFI system table. + +--- + grub-core/loader/i386/bsd.c | 8 ++++++++ + include/grub/i386/netbsd_bootinfo.h | 7 +++++++ + ChangeLog | 5 +++++ + 3 files changed, 20 insertions(+) + +diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c +index 41ef9109ee1..8f691e0e2d1 100644 +--- a/grub-core/loader/i386/bsd.c ++++ b/grub-core/loader/i386/bsd.c +@@ -1145,6 +1145,14 @@ grub_netbsd_boot (void) + if (err) + return err; + ++#ifdef GRUB_MACHINE_EFI ++ err = grub_bsd_add_meta (NETBSD_BTINFO_EFI, ++ &grub_efi_system_table, ++ sizeof (grub_efi_system_table)); ++ if (err) ++ return err; ++#endif ++ + { + struct bsd_tag *tag; + tag_buf_len = 0; +diff --git a/include/grub/i386/netbsd_bootinfo.h b/include/grub/i386/netbsd_bootinfo.h +index e48c19b4089..9b4f4604103 100644 +--- a/include/grub/i386/netbsd_bootinfo.h ++++ b/include/grub/i386/netbsd_bootinfo.h +@@ -58,6 +58,8 @@ + #define NETBSD_BTINFO_BOOTWEDGE 10 + #define NETBSD_BTINFO_MODULES 11 + #define NETBSD_BTINFO_FRAMEBUF 12 ++#define NETBSD_BTINFO_USERCONFCOMMANDS 13 ++#define NETBSD_BTINFO_EFI 14 + + struct grub_netbsd_bootinfo + { +@@ -146,4 +148,9 @@ struct grub_netbsd_btinfo_framebuf + + #define GRUB_NETBSD_MAX_ROOTDEVICE_LEN 16 + ++struct grub_netbsd_btinfo_efi ++{ ++ void *pa_systbl; /* Physical address of the EFI System Table */ ++}; ++ + #endif +diff --git a/ChangeLog b/ChangeLog +index abf8f4b2716..0cdd095a498 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2014-06-21 Stephane Rochoy ++ ++ * grub-core/loader/i386/bsd.c (grub_netbsd_boot): Pass pointer to ++ EFI system table. ++ + 2014-06-21 Stephane Rochoy + + * grub-core/commands/efi/lsefisystab.c (grub_cmd_lsefisystab): Show diff --git a/SOURCES/0086-util-grub-install.c-Fix-handling-of-disk-module.patch b/SOURCES/0086-util-grub-install.c-Fix-handling-of-disk-module.patch new file mode 100644 index 0000000..ab838fa --- /dev/null +++ b/SOURCES/0086-util-grub-install.c-Fix-handling-of-disk-module.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Glenn Washburn +Date: Sun, 22 Jun 2014 01:45:11 +0200 +Subject: [PATCH] * util/grub-install.c: Fix handling of --disk-module. + +--- + util/grub-install.c | 3 +-- + ChangeLog | 4 ++++ + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/util/grub-install.c b/util/grub-install.c +index e9c6a4656ef..7d61c32be2f 100644 +--- a/util/grub-install.c ++++ b/util/grub-install.c +@@ -94,7 +94,6 @@ enum + OPTION_RECHECK, + OPTION_FORCE, + OPTION_FORCE_FILE_ID, +- OPTION_MODULE, + OPTION_NO_NVRAM, + OPTION_REMOVABLE, + OPTION_BOOTLOADER_ID, +@@ -273,7 +272,7 @@ static struct argp_option options[] = { + N_("install even if problems are detected"), 2}, + {"force-file-id", OPTION_FORCE_FILE_ID, 0, 0, + N_("use identifier file even if UUID is available"), 2}, +- {"disk-module", OPTION_MODULE, N_("MODULE"), 0, ++ {"disk-module", OPTION_DISK_MODULE, N_("MODULE"), 0, + N_("disk module to use (biosdisk or native). " + "This option is only available on BIOS target."), 2}, + {"no-nvram", OPTION_NO_NVRAM, 0, 0, +diff --git a/ChangeLog b/ChangeLog +index 0cdd095a498..4ce664327f9 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2014-06-21 Glenn Washburn ++ ++ * util/grub-install.c: Fix handling of --disk-module. ++ + 2014-06-21 Stephane Rochoy + + * grub-core/loader/i386/bsd.c (grub_netbsd_boot): Pass pointer to diff --git a/SOURCES/0087-grub-core-commands-loadenv.c-check_blocklists-Fix-ov.patch b/SOURCES/0087-grub-core-commands-loadenv.c-check_blocklists-Fix-ov.patch new file mode 100644 index 0000000..994ad08 --- /dev/null +++ b/SOURCES/0087-grub-core-commands-loadenv.c-check_blocklists-Fix-ov.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=D0=A0=D0=BE=D0=BC=D0=B0=D0=BD=20=D0=9F=D0=B5=D1=85=D0=BE?= + =?UTF-8?q?=D0=B2?= +Date: Sun, 22 Jun 2014 03:51:50 +0400 +Subject: [PATCH] * grub-core/commands/loadenv.c (check_blocklists): Fix + overlap check. + +--- + grub-core/commands/loadenv.c | 13 ++----------- + ChangeLog | 4 ++++ + 2 files changed, 6 insertions(+), 11 deletions(-) + +diff --git a/grub-core/commands/loadenv.c b/grub-core/commands/loadenv.c +index 6af81120745..acd93d123ed 100644 +--- a/grub-core/commands/loadenv.c ++++ b/grub-core/commands/loadenv.c +@@ -263,7 +263,7 @@ check_blocklists (grub_envblk_t envblk, struct blocklist *blocklists, + for (q = p->next; q; q = q->next) + { + grub_disk_addr_t s1, s2; +- grub_disk_addr_t e1, e2, t; ++ grub_disk_addr_t e1, e2; + + s1 = p->sector; + e1 = s1 + ((p->length + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS); +@@ -271,16 +271,7 @@ check_blocklists (grub_envblk_t envblk, struct blocklist *blocklists, + s2 = q->sector; + e2 = s2 + ((q->length + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS); + +- if (s2 > s1) +- { +- t = s2; +- s2 = s1; +- s1 = t; +- t = e2; +- e2 = e1; +- e1 = t; +- } +- if (e1 > s2) ++ if (s1 < e2 && s2 < e1) + { + /* This might be actually valid, but it is unbelievable that + any filesystem makes such a silly allocation. */ +diff --git a/ChangeLog b/ChangeLog +index 4ce664327f9..a2da9743231 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2014-06-21 Роман Пехов ++ ++ * grub-core/commands/loadenv.c (check_blocklists): Fix overlap check. ++ + 2014-06-21 Glenn Washburn + + * util/grub-install.c: Fix handling of --disk-module. diff --git a/SOURCES/0088-NEWS-The-cmosclean-command-in-fact-dates-back-to-1.9.patch b/SOURCES/0088-NEWS-The-cmosclean-command-in-fact-dates-back-to-1.9.patch new file mode 100644 index 0000000..b3bde1e --- /dev/null +++ b/SOURCES/0088-NEWS-The-cmosclean-command-in-fact-dates-back-to-1.9.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Colin Watson +Date: Sat, 28 Dec 2013 02:20:27 +0000 +Subject: [PATCH] * NEWS: The cmosclean command in fact dates back to 1.99. + Remove mention of it from 2.02. + +--- + NEWS | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/NEWS b/NEWS +index a61df942a35..f621c65de06 100644 +--- a/NEWS ++++ b/NEWS +@@ -63,6 +63,8 @@ New in 2.02: + * New `efifwsetup' and `lsefi' commands on EFI platforms. + * New `cmosdump' and `cmosset' commands on platforms with CMOS support. + * New command `pcidump' for PCI platforms. ++ * New `cbmemc', `coreboot_boottime', and `lscoreboot' commands on ++ coreboot. + * Improve opcode parsing in ACPI halt implementation. + * Use the TSC as a possible time source on i386-ieee1275. + * Merge PowerPC grub-mkrescue implementation with the common one. diff --git a/SOURCES/0089-Migrate-PPC-from-Yaboot-to-Grub2.patch b/SOURCES/0089-Migrate-PPC-from-Yaboot-to-Grub2.patch new file mode 100644 index 0000000..68086cd --- /dev/null +++ b/SOURCES/0089-Migrate-PPC-from-Yaboot-to-Grub2.patch @@ -0,0 +1,151 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Hamzy +Date: Wed, 28 Mar 2012 14:46:41 -0500 +Subject: [PATCH] Migrate PPC from Yaboot to Grub2 + +Add configuration support for serial terminal consoles. This will set the +maximum screen size so that text is not overwritten. +--- + Makefile.util.def | 7 +++ + util/grub.d/20_ppc_terminfo.in | 114 +++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 121 insertions(+) + create mode 100644 util/grub.d/20_ppc_terminfo.in + +diff --git a/Makefile.util.def b/Makefile.util.def +index a286a89cd8d..8f40e78332a 100644 +--- a/Makefile.util.def ++++ b/Makefile.util.def +@@ -484,6 +484,13 @@ script = { + condition = COND_HOST_LINUX; + }; + ++script = { ++ name = '20_ppc_terminfo'; ++ common = util/grub.d/20_ppc_terminfo.in; ++ installdir = grubconf; ++ condition = COND_HOST_LINUX; ++}; ++ + script = { + name = '30_os-prober'; + common = util/grub.d/30_os-prober.in; +diff --git a/util/grub.d/20_ppc_terminfo.in b/util/grub.d/20_ppc_terminfo.in +new file mode 100644 +index 00000000000..10d66586820 +--- /dev/null ++++ b/util/grub.d/20_ppc_terminfo.in +@@ -0,0 +1,114 @@ ++#! /bin/sh ++set -e ++ ++# grub-mkconfig helper script. ++# Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc. ++# ++# GRUB is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++# ++# GRUB is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with GRUB. If not, see . ++ ++prefix=@prefix@ ++exec_prefix=@exec_prefix@ ++bindir=@bindir@ ++libdir=@libdir@ ++. "@datadir@/@PACKAGE@/grub-mkconfig_lib" ++ ++export TEXTDOMAIN=@PACKAGE@ ++export TEXTDOMAINDIR=@localedir@ ++ ++X=80 ++Y=24 ++TERMINAL=ofconsole ++ ++argument () { ++ opt=$1 ++ shift ++ ++ if test $# -eq 0; then ++ echo "$0: option requires an argument -- '$opt'" 1>&2 ++ exit 1 ++ fi ++ echo $1 ++} ++ ++check_terminfo () { ++ ++ while test $# -gt 0 ++ do ++ option=$1 ++ shift ++ ++ case "$option" in ++ terminfo | TERMINFO) ++ ;; ++ ++ -g) ++ NEWXY=`argument $option "$@"` ++ NEWX=`echo $NEWXY | cut -d x -f 1` ++ NEWY=`echo $NEWXY | cut -d x -f 2` ++ ++ if [ ${NEWX} -ge 80 ] ; then ++ X=${NEWX} ++ else ++ echo "Warning: ${NEWX} is less than the minimum size of 80" ++ fi ++ ++ if [ ${NEWY} -ge 24 ] ; then ++ Y=${NEWY} ++ else ++ echo "Warning: ${NEWY} is less than the minimum size of 24" ++ fi ++ ++ shift ++ ;; ++ ++ *) ++# # accept console or ofconsole ++# if [ "$option" != "console" -a "$option" != "ofconsole" ] ; then ++# echo "Error: GRUB_TERMINFO unknown console: $option" ++# exit 1 ++# fi ++# # perfer console ++# TERMINAL=console ++ # accept ofconsole ++ if [ "$option" != "ofconsole" ] ; then ++ echo "Error: GRUB_TERMINFO unknown console: $option" ++ exit 1 ++ fi ++ # perfer console ++ TERMINAL=ofconsole ++ ;; ++ esac ++ ++ done ++ ++} ++ ++if ! uname -m | grep -q ppc ; then ++ exit 0 ++fi ++ ++if [ "x${GRUB_TERMINFO}" != "x" ] ; then ++ F1=`echo ${GRUB_TERMINFO} | cut -d " " -f 1` ++ ++ if [ "${F1}" != "terminfo" ] ; then ++ echo "Error: GRUB_TERMINFO is set to \"${GRUB_TERMINFO}\" The first word should be terminfo." ++ exit 1 ++ fi ++ ++ check_terminfo ${GRUB_TERMINFO} ++fi ++ ++cat << EOF ++ terminfo -g ${X}x${Y} ${TERMINAL} ++EOF diff --git a/SOURCES/0090-Add-fw_path-variable-revised.patch b/SOURCES/0090-Add-fw_path-variable-revised.patch new file mode 100644 index 0000000..80510db --- /dev/null +++ b/SOURCES/0090-Add-fw_path-variable-revised.patch @@ -0,0 +1,78 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paulo Flabiano Smorigo +Date: Wed, 19 Sep 2012 21:22:55 -0300 +Subject: [PATCH] Add fw_path variable (revised) + +This patch makes grub look for its config file on efi where the app was +found. It was originally written by Matthew Garrett, and adapted to fix the +"No modules are loaded on grub2 network boot" issue: + +https://bugzilla.redhat.com/show_bug.cgi?id=857936 +--- + grub-core/kern/main.c | 13 ++++++------- + grub-core/normal/main.c | 25 ++++++++++++++++++++++++- + 2 files changed, 30 insertions(+), 8 deletions(-) + +diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c +index 9cad0c4485c..8ab7794c47b 100644 +--- a/grub-core/kern/main.c ++++ b/grub-core/kern/main.c +@@ -127,16 +127,15 @@ grub_set_prefix_and_root (void) + + grub_machine_get_bootlocation (&fwdevice, &fwpath); + +- if (fwdevice) ++ if (fwdevice && fwpath) + { +- char *cmdpath; ++ char *fw_path; + +- cmdpath = grub_xasprintf ("(%s)%s", fwdevice, fwpath ? : ""); +- if (cmdpath) ++ fw_path = grub_xasprintf ("(%s)/%s", fwdevice, fwpath); ++ if (fw_path) + { +- grub_env_set ("cmdpath", cmdpath); +- grub_env_export ("cmdpath"); +- grub_free (cmdpath); ++ grub_env_set ("fw_path", fw_path); ++ grub_free (fw_path); + } + } + +diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c +index 3a926fc5fa9..6f4970f71c1 100644 +--- a/grub-core/normal/main.c ++++ b/grub-core/normal/main.c +@@ -319,7 +319,30 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), + /* Guess the config filename. It is necessary to make CONFIG static, + so that it won't get broken by longjmp. */ + char *config; +- const char *prefix; ++ const char *prefix, *fw_path; ++ ++ fw_path = grub_env_get ("fw_path"); ++ if (fw_path) ++ { ++ config = grub_xasprintf ("%s/grub.cfg", fw_path); ++ if (config) ++ { ++ grub_file_t file; ++ ++ file = grub_file_open (config); ++ if (file) ++ { ++ grub_file_close (file); ++ grub_enter_normal_mode (config); ++ } ++ else ++ { ++ /* Ignore all errors. */ ++ grub_errno = 0; ++ } ++ grub_free (config); ++ } ++ } + + prefix = grub_env_get ("prefix"); + if (prefix) diff --git a/SOURCES/0091-Add-support-for-linuxefi.patch b/SOURCES/0091-Add-support-for-linuxefi.patch new file mode 100644 index 0000000..4738452 --- /dev/null +++ b/SOURCES/0091-Add-support-for-linuxefi.patch @@ -0,0 +1,479 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Tue, 10 Jul 2012 11:58:52 -0400 +Subject: [PATCH] Add support for linuxefi + +--- + grub-core/Makefile.core.def | 8 + + grub-core/kern/efi/mm.c | 32 ++++ + grub-core/loader/i386/efi/linux.c | 371 ++++++++++++++++++++++++++++++++++++++ + include/grub/efi/efi.h | 3 + + include/grub/i386/linux.h | 1 + + 5 files changed, 415 insertions(+) + create mode 100644 grub-core/loader/i386/efi/linux.c + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 42443bc00b9..ec46506e39e 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -1705,6 +1705,14 @@ module = { + enable = x86_64_efi; + }; + ++module = { ++ name = linuxefi; ++ efi = loader/i386/efi/linux.c; ++ efi = lib/cmdline.c; ++ enable = i386_efi; ++ enable = x86_64_efi; ++}; ++ + module = { + name = chain; + efi = loader/efi/chainloader.c; +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index be37afd9dc4..ddeca6073f6 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -49,6 +49,38 @@ static grub_efi_uintn_t finish_desc_size; + static grub_efi_uint32_t finish_desc_version; + int grub_efi_is_finished = 0; + ++/* Allocate pages below a specified address */ ++void * ++grub_efi_allocate_pages_max (grub_efi_physical_address_t max, ++ grub_efi_uintn_t pages) ++{ ++ grub_efi_status_t status; ++ grub_efi_boot_services_t *b; ++ grub_efi_physical_address_t address = max; ++ ++ if (max > 0xffffffff) ++ return 0; ++ ++ b = grub_efi_system_table->boot_services; ++ status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA, pages, &address); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ return 0; ++ ++ if (address == 0) ++ { ++ /* Uggh, the address 0 was allocated... This is too annoying, ++ so reallocate another one. */ ++ address = max; ++ status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA, pages, &address); ++ grub_efi_free_pages (0, pages); ++ if (status != GRUB_EFI_SUCCESS) ++ return 0; ++ } ++ ++ return (void *) ((grub_addr_t) address); ++} ++ + /* Allocate pages. Return the pointer to the first of allocated pages. */ + void * + grub_efi_allocate_pages (grub_efi_physical_address_t address, +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +new file mode 100644 +index 00000000000..b79e6320ba9 +--- /dev/null ++++ b/grub-core/loader/i386/efi/linux.c +@@ -0,0 +1,371 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2012 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++static grub_dl_t my_mod; ++static int loaded; ++static void *kernel_mem; ++static grub_uint64_t kernel_size; ++static grub_uint8_t *initrd_mem; ++static grub_uint32_t handover_offset; ++struct linux_kernel_params *params; ++static char *linux_cmdline; ++ ++#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12) ++ ++#define SHIM_LOCK_GUID \ ++ { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} } ++ ++struct grub_efi_shim_lock ++{ ++ grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size); ++}; ++typedef struct grub_efi_shim_lock grub_efi_shim_lock_t; ++ ++static grub_efi_boolean_t ++grub_linuxefi_secure_validate (void *data, grub_uint32_t size) ++{ ++ grub_efi_guid_t guid = SHIM_LOCK_GUID; ++ grub_efi_shim_lock_t *shim_lock; ++ ++ shim_lock = grub_efi_locate_protocol(&guid, NULL); ++ ++ if (!shim_lock) ++ return 1; ++ ++ if (shim_lock->verify(data, size) == GRUB_EFI_SUCCESS) ++ return 1; ++ ++ return 0; ++} ++ ++typedef void(*handover_func)(void *, grub_efi_system_table_t *, struct linux_kernel_params *); ++ ++static grub_err_t ++grub_linuxefi_boot (void) ++{ ++ handover_func hf; ++ int offset = 0; ++ ++#ifdef __x86_64__ ++ offset = 512; ++#endif ++ ++ hf = (handover_func)((char *)kernel_mem + handover_offset + offset); ++ ++ asm volatile ("cli"); ++ ++ hf (grub_efi_image_handle, grub_efi_system_table, params); ++ ++ /* Not reached */ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_linuxefi_unload (void) ++{ ++ grub_dl_unref (my_mod); ++ loaded = 0; ++ if (initrd_mem) ++ grub_efi_free_pages((grub_efi_physical_address_t)initrd_mem, BYTES_TO_PAGES(params->ramdisk_size)); ++ if (linux_cmdline) ++ grub_efi_free_pages((grub_efi_physical_address_t)linux_cmdline, BYTES_TO_PAGES(params->cmdline_size + 1)); ++ if (kernel_mem) ++ grub_efi_free_pages((grub_efi_physical_address_t)kernel_mem, BYTES_TO_PAGES(kernel_size)); ++ if (params) ++ grub_efi_free_pages((grub_efi_physical_address_t)params, BYTES_TO_PAGES(16384)); ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), ++ int argc, char *argv[]) ++{ ++ grub_file_t *files = 0; ++ int i, nfiles = 0; ++ grub_size_t size = 0; ++ grub_uint8_t *ptr; ++ ++ if (argc == 0) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); ++ goto fail; ++ } ++ ++ if (!loaded) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first")); ++ goto fail; ++ } ++ ++ files = grub_zalloc (argc * sizeof (files[0])); ++ if (!files) ++ goto fail; ++ ++ for (i = 0; i < argc; i++) ++ { ++ grub_file_filter_disable_compression (); ++ files[i] = grub_file_open (argv[i]); ++ if (! files[i]) ++ goto fail; ++ nfiles++; ++ size += ALIGN_UP (grub_file_size (files[i]), 4); ++ } ++ ++ initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size)); ++ ++ if (!initrd_mem) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd")); ++ goto fail; ++ } ++ ++ params->ramdisk_size = size; ++ params->ramdisk_image = (grub_uint32_t)(grub_uint64_t) initrd_mem; ++ ++ ptr = initrd_mem; ++ ++ for (i = 0; i < nfiles; i++) ++ { ++ grub_ssize_t cursize = grub_file_size (files[i]); ++ if (grub_file_read (files[i], ptr, cursize) != cursize) ++ { ++ if (!grub_errno) ++ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), ++ argv[i]); ++ goto fail; ++ } ++ ptr += cursize; ++ grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4)); ++ ptr += ALIGN_UP_OVERHEAD (cursize, 4); ++ } ++ ++ params->ramdisk_size = size; ++ ++ fail: ++ for (i = 0; i < nfiles; i++) ++ grub_file_close (files[i]); ++ grub_free (files); ++ ++ if (initrd_mem && grub_errno) ++ grub_efi_free_pages((grub_efi_physical_address_t)initrd_mem, BYTES_TO_PAGES(size)); ++ ++ return grub_errno; ++} ++ ++static grub_err_t ++grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), ++ int argc, char *argv[]) ++{ ++ grub_file_t file = 0; ++ struct linux_kernel_header lh; ++ grub_ssize_t len, start, filelen; ++ void *kernel; ++ ++ grub_dl_ref (my_mod); ++ ++ if (argc == 0) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); ++ goto fail; ++ } ++ ++ file = grub_file_open (argv[0]); ++ if (! file) ++ goto fail; ++ ++ filelen = grub_file_size (file); ++ ++ kernel = grub_malloc(filelen); ++ ++ if (!kernel) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer")); ++ goto fail; ++ } ++ ++ if (grub_file_read (file, kernel, filelen) != filelen) ++ { ++ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"), argv[0]); ++ goto fail; ++ } ++ ++ if (! grub_linuxefi_secure_validate (kernel, filelen)) ++ { ++ grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]); ++ grub_free (kernel); ++ goto fail; ++ } ++ ++ grub_file_seek (file, 0); ++ ++ grub_free(kernel); ++ ++ params = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(16384)); ++ ++ if (! params) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters"); ++ goto fail; ++ } ++ ++ memset (params, 0, 16384); ++ ++ if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) ++ { ++ if (!grub_errno) ++ grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), ++ argv[0]); ++ goto fail; ++ } ++ ++ if (lh.boot_flag != grub_cpu_to_le16 (0xaa55)) ++ { ++ grub_error (GRUB_ERR_BAD_OS, N_("invalid magic number")); ++ goto fail; ++ } ++ ++ if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS) ++ { ++ grub_error (GRUB_ERR_BAD_OS, N_("too many setup sectors")); ++ goto fail; ++ } ++ ++ if (lh.version < grub_cpu_to_le16 (0x020b)) ++ { ++ grub_error (GRUB_ERR_BAD_OS, N_("kernel too old")); ++ goto fail; ++ } ++ ++ if (!lh.handover_offset) ++ { ++ grub_error (GRUB_ERR_BAD_OS, N_("kernel doesn't support EFI handover")); ++ goto fail; ++ } ++ ++ linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff, ++ BYTES_TO_PAGES(lh.cmdline_size + 1)); ++ ++ if (!linux_cmdline) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline")); ++ goto fail; ++ } ++ ++ grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE)); ++ grub_create_loader_cmdline (argc, argv, ++ linux_cmdline + sizeof (LINUX_IMAGE) - 1, ++ lh.cmdline_size - (sizeof (LINUX_IMAGE) - 1)); ++ ++ lh.cmd_line_ptr = (grub_uint32_t)(grub_uint64_t)linux_cmdline; ++ ++ handover_offset = lh.handover_offset; ++ ++ start = (lh.setup_sects + 1) * 512; ++ len = grub_file_size(file) - start; ++ ++ kernel_mem = grub_efi_allocate_pages(lh.pref_address, ++ BYTES_TO_PAGES(lh.init_size)); ++ ++ if (!kernel_mem) ++ kernel_mem = grub_efi_allocate_pages_max(0x3fffffff, ++ BYTES_TO_PAGES(lh.init_size)); ++ ++ if (!kernel_mem) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel")); ++ goto fail; ++ } ++ ++ if (grub_file_seek (file, start) == (grub_off_t) -1) ++ { ++ grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), ++ argv[0]); ++ goto fail; ++ } ++ ++ if (grub_file_read (file, kernel_mem, len) != len && !grub_errno) ++ { ++ grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), ++ argv[0]); ++ } ++ ++ if (grub_errno == GRUB_ERR_NONE) ++ { ++ grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0); ++ loaded = 1; ++ lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem; ++ } ++ ++ memcpy(params, &lh, 2 * 512); ++ ++ params->type_of_loader = 0x21; ++ ++ fail: ++ ++ if (file) ++ grub_file_close (file); ++ ++ if (grub_errno != GRUB_ERR_NONE) ++ { ++ grub_dl_unref (my_mod); ++ loaded = 0; ++ } ++ ++ if (linux_cmdline && !loaded) ++ grub_efi_free_pages((grub_efi_physical_address_t)linux_cmdline, BYTES_TO_PAGES(lh.cmdline_size + 1)); ++ ++ if (kernel_mem && !loaded) ++ grub_efi_free_pages((grub_efi_physical_address_t)kernel_mem, BYTES_TO_PAGES(kernel_size)); ++ ++ if (params && !loaded) ++ grub_efi_free_pages((grub_efi_physical_address_t)params, BYTES_TO_PAGES(16384)); ++ ++ return grub_errno; ++} ++ ++static grub_command_t cmd_linux, cmd_initrd; ++ ++GRUB_MOD_INIT(linuxefi) ++{ ++ cmd_linux = ++ grub_register_command ("linuxefi", grub_cmd_linux, ++ 0, N_("Load Linux.")); ++ cmd_initrd = ++ grub_register_command ("initrdefi", grub_cmd_initrd, ++ 0, N_("Load initrd.")); ++ my_mod = mod; ++} ++ ++GRUB_MOD_FINI(linuxefi) ++{ ++ grub_unregister_command (cmd_linux); ++ grub_unregister_command (cmd_initrd); ++} +diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h +index 489cf9e6da7..9370fd53096 100644 +--- a/include/grub/efi/efi.h ++++ b/include/grub/efi/efi.h +@@ -40,6 +40,9 @@ void EXPORT_FUNC(grub_efi_stall) (grub_efi_uintn_t microseconds); + void * + EXPORT_FUNC(grub_efi_allocate_pages) (grub_efi_physical_address_t address, + grub_efi_uintn_t pages); ++void * ++EXPORT_FUNC(grub_efi_allocate_pages_max) (grub_efi_physical_address_t max, ++ grub_efi_uintn_t pages); + void EXPORT_FUNC(grub_efi_free_pages) (grub_efi_physical_address_t address, + grub_efi_uintn_t pages); + int +diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h +index da0ca3b83cd..fc36bdaf367 100644 +--- a/include/grub/i386/linux.h ++++ b/include/grub/i386/linux.h +@@ -139,6 +139,7 @@ struct linux_kernel_header + grub_uint64_t setup_data; + grub_uint64_t pref_address; + grub_uint32_t init_size; ++ grub_uint32_t handover_offset; + } GRUB_PACKED; + + /* Boot parameters for Linux based on 2.6.12. This is used by the setup diff --git a/SOURCES/0092-Use-linuxefi-and-initrdefi-where-appropriate.patch b/SOURCES/0092-Use-linuxefi-and-initrdefi-where-appropriate.patch new file mode 100644 index 0000000..99a024d --- /dev/null +++ b/SOURCES/0092-Use-linuxefi-and-initrdefi-where-appropriate.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 16 Jul 2012 18:57:11 -0400 +Subject: [PATCH] Use "linuxefi" and "initrdefi" where appropriate. + +--- + util/grub.d/10_linux.in | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index 00d193159e9..ad34cc02d36 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -127,17 +127,31 @@ linux_entry () + printf '%s\n' "${prepare_boot_cache}" | sed "s/^/$submenu_indentation/" + fi + message="$(gettext_printf "Loading Linux %s ..." ${version})" +- sed "s/^/$submenu_indentation/" << EOF ++ if [ -d /sys/firmware/efi ]; then ++ sed "s/^/$submenu_indentation/" << EOF ++ echo '$(echo "$message" | grub_quote)' ++ linuxefi ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args} ++EOF ++ else ++ sed "s/^/$submenu_indentation/" << EOF + echo '$(echo "$message" | grub_quote)' + linux ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args} + EOF ++ fi + if test -n "${initrd}" ; then + # TRANSLATORS: ramdisk isn't identifier. Should be translated. + message="$(gettext_printf "Loading initial ramdisk ...")" +- sed "s/^/$submenu_indentation/" << EOF ++ if [ -d /sys/firmware/efi ]; then ++ sed "s/^/$submenu_indentation/" << EOF + echo '$(echo "$message" | grub_quote)' ++ initrdefi ${rel_dirname}/${initrd} ++EOF ++ else ++ sed "s/^/$submenu_indentation/" << EOF ++ echo '$message' + initrd ${rel_dirname}/${initrd} + EOF ++ fi + fi + sed "s/^/$submenu_indentation/" << EOF + } diff --git a/SOURCES/0093-Don-t-allow-insmod-when-secure-boot-is-enabled.patch b/SOURCES/0093-Don-t-allow-insmod-when-secure-boot-is-enabled.patch new file mode 100644 index 0000000..78b6685 --- /dev/null +++ b/SOURCES/0093-Don-t-allow-insmod-when-secure-boot-is-enabled.patch @@ -0,0 +1,114 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Colin Watson +Date: Tue, 23 Oct 2012 10:40:49 -0400 +Subject: [PATCH] Don't allow insmod when secure boot is enabled. + +Hi, + +Fedora's patch to forbid insmod in UEFI Secure Boot environments is fine +as far as it goes. However, the insmod command is not the only way that +modules can be loaded. In particular, the 'normal' command, which +implements the usual GRUB menu and the fully-featured command prompt, +will implicitly load commands not currently loaded into memory. This +permits trivial Secure Boot violations by writing commands implementing +whatever you want to do and pointing $prefix at the malicious code. + +I'm currently test-building this patch (replacing your current +grub-2.00-no-insmod-on-sb.patch), but this should be more correct. It +moves the check into grub_dl_load_file. +--- + grub-core/kern/dl.c | 21 +++++++++++++++++++++ + grub-core/kern/efi/efi.c | 28 ++++++++++++++++++++++++++++ + include/grub/efi/efi.h | 1 + + 3 files changed, 50 insertions(+) + +diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c +index 6850e049741..b0b0405fcbe 100644 +--- a/grub-core/kern/dl.c ++++ b/grub-core/kern/dl.c +@@ -38,6 +38,14 @@ + #define GRUB_MODULES_MACHINE_READONLY + #endif + ++#ifdef GRUB_MACHINE_EMU ++#include ++#endif ++ ++#ifdef GRUB_MACHINE_EFI ++#include ++#endif ++ + + + #pragma GCC diagnostic ignored "-Wcast-align" +@@ -680,6 +688,19 @@ grub_dl_load_file (const char *filename) + void *core = 0; + grub_dl_t mod = 0; + ++#ifdef GRUB_MACHINE_EFI ++ if (grub_efi_secure_boot ()) ++ { ++#if 0 ++ /* This is an error, but grub2-mkconfig still generates a pile of ++ * insmod commands, so emitting it would be mostly just obnoxious. */ ++ grub_error (GRUB_ERR_ACCESS_DENIED, ++ "Secure Boot forbids loading module from %s", filename); ++#endif ++ return 0; ++ } ++#endif ++ + grub_boot_time ("Loading module %s", filename); + + file = grub_file_open (filename); +diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c +index b9eb1ab1e33..cd839cc988a 100644 +--- a/grub-core/kern/efi/efi.c ++++ b/grub-core/kern/efi/efi.c +@@ -259,6 +259,34 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid, + return NULL; + } + ++grub_efi_boolean_t ++grub_efi_secure_boot (void) ++{ ++ grub_efi_guid_t efi_var_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID; ++ grub_size_t datasize; ++ char *secure_boot = NULL; ++ char *setup_mode = NULL; ++ grub_efi_boolean_t ret = 0; ++ ++ secure_boot = grub_efi_get_variable("SecureBoot", &efi_var_guid, &datasize); ++ ++ if (datasize != 1 || !secure_boot) ++ goto out; ++ ++ setup_mode = grub_efi_get_variable("SetupMode", &efi_var_guid, &datasize); ++ ++ if (datasize != 1 || !setup_mode) ++ goto out; ++ ++ if (*secure_boot && !*setup_mode) ++ ret = 1; ++ ++ out: ++ grub_free (secure_boot); ++ grub_free (setup_mode); ++ return ret; ++} ++ + #pragma GCC diagnostic ignored "-Wcast-align" + + /* Search the mods section from the PE32/PE32+ image. This code uses +diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h +index 9370fd53096..a000c383e81 100644 +--- a/include/grub/efi/efi.h ++++ b/include/grub/efi/efi.h +@@ -72,6 +72,7 @@ EXPORT_FUNC (grub_efi_set_variable) (const char *var, + const grub_efi_guid_t *guid, + void *data, + grub_size_t datasize); ++grub_efi_boolean_t EXPORT_FUNC (grub_efi_secure_boot) (void); + int + EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1, + const grub_efi_device_path_t *dp2); diff --git a/SOURCES/0094-Pass-x-hex-hex-straight-through-unmolested.patch b/SOURCES/0094-Pass-x-hex-hex-straight-through-unmolested.patch new file mode 100644 index 0000000..c51c06a --- /dev/null +++ b/SOURCES/0094-Pass-x-hex-hex-straight-through-unmolested.patch @@ -0,0 +1,179 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 1 Oct 2012 13:24:37 -0400 +Subject: [PATCH] Pass "\x[[:hex:]][[:hex:]]" straight through unmolested. + +--- + grub-core/commands/wildcard.c | 16 +++++++++++++++- + grub-core/lib/cmdline.c | 34 ++++++++++++++++++++++++++++++++-- + grub-core/script/execute.c | 43 +++++++++++++++++++++++++++++++++++++------ + 3 files changed, 84 insertions(+), 9 deletions(-) + +diff --git a/grub-core/commands/wildcard.c b/grub-core/commands/wildcard.c +index 2807f806bd4..0f40e041541 100644 +--- a/grub-core/commands/wildcard.c ++++ b/grub-core/commands/wildcard.c +@@ -458,6 +458,12 @@ check_file (const char *dir, const char *basename) + return ctx.found; + } + ++static int ++is_hex(char c) ++{ ++ return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); ++} ++ + static void + unescape (char *out, const char *in, const char *end) + { +@@ -466,7 +472,15 @@ unescape (char *out, const char *in, const char *end) + + for (optr = out, iptr = in; iptr < end;) + { +- if (*iptr == '\\' && iptr + 1 < end) ++ if (*iptr == '\\' && iptr + 3 < end && iptr[1] == 'x' && is_hex(iptr[2]) && is_hex(iptr[3])) ++ { ++ *optr++ = *iptr++; ++ *optr++ = *iptr++; ++ *optr++ = *iptr++; ++ *optr++ = *iptr++; ++ continue; ++ } ++ else if (*iptr == '\\' && iptr + 1 < end) + { + *optr++ = iptr[1]; + iptr += 2; +diff --git a/grub-core/lib/cmdline.c b/grub-core/lib/cmdline.c +index d5e10ee8798..0a5b2afb94b 100644 +--- a/grub-core/lib/cmdline.c ++++ b/grub-core/lib/cmdline.c +@@ -20,6 +20,12 @@ + #include + #include + ++static int ++is_hex(char c) ++{ ++ return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); ++} ++ + static unsigned int check_arg (char *c, int *has_space) + { + int space = 0; +@@ -27,7 +33,13 @@ static unsigned int check_arg (char *c, int *has_space) + + while (*c) + { +- if (*c == '\\' || *c == '\'' || *c == '"') ++ if (*c == '\\' && *(c+1) == 'x' && is_hex(*(c+2)) && is_hex(*(c+3))) ++ { ++ size += 4; ++ c += 4; ++ continue; ++ } ++ else if (*c == '\\' || *c == '\'' || *c == '"') + size++; + else if (*c == ' ') + space = 1; +@@ -85,7 +97,25 @@ int grub_create_loader_cmdline (int argc, char *argv[], char *buf, + + while (*c) + { +- if (*c == '\\' || *c == '\'' || *c == '"') ++ if (*c == ' ') ++ { ++ *buf++ = '\\'; ++ *buf++ = 'x'; ++ *buf++ = '2'; ++ *buf++ = '0'; ++ c++; ++ continue; ++ } ++ else if (*c == '\\' && *(c+1) == 'x' && ++ is_hex(*(c+2)) && is_hex(*(c+3))) ++ { ++ *buf++ = *c++; ++ *buf++ = *c++; ++ *buf++ = *c++; ++ *buf++ = *c++; ++ continue; ++ } ++ else if (*c == '\\' || *c == '\'' || *c == '"') + *buf++ = '\\'; + + *buf++ = *c; +diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c +index afd551320f7..8f01c1bbfa2 100644 +--- a/grub-core/script/execute.c ++++ b/grub-core/script/execute.c +@@ -52,6 +52,12 @@ static struct grub_script_scope *scope = 0; + /* Wildcard translator for GRUB script. */ + struct grub_script_wildcard_translator *grub_wildcard_translator; + ++static int ++is_hex(char c) ++{ ++ return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); ++} ++ + static char* + wildcard_escape (const char *s) + { +@@ -68,7 +74,15 @@ wildcard_escape (const char *s) + i = 0; + while ((ch = *s++)) + { +- if (ch == '*' || ch == '\\' || ch == '?') ++ if (ch == '\\' && s[0] == 'x' && is_hex(s[1]) && is_hex(s[2])) ++ { ++ p[i++] = ch; ++ p[i++] = *s++; ++ p[i++] = *s++; ++ p[i++] = *s++; ++ continue; ++ } ++ else if (ch == '*' || ch == '\\' || ch == '?') + p[i++] = '\\'; + p[i++] = ch; + } +@@ -92,7 +106,14 @@ wildcard_unescape (const char *s) + i = 0; + while ((ch = *s++)) + { +- if (ch == '\\') ++ if (ch == '\\' && s[0] == 'x' && is_hex(s[1]) && is_hex(s[2])) ++ { ++ p[i++] = '\\'; ++ p[i++] = *s++; ++ p[i++] = *s++; ++ p[i++] = *s++; ++ } ++ else if (ch == '\\') + p[i++] = *s++; + else + p[i++] = ch; +@@ -394,10 +415,20 @@ parse_string (const char *str, + switch (*ptr) + { + case '\\': +- escaped = !escaped; +- if (!escaped && put) +- *(put++) = '\\'; +- ptr++; ++ if (!escaped && put && *(ptr+1) == 'x' && is_hex(*(ptr+2)) && is_hex(*(ptr+3))) ++ { ++ *(put++) = *ptr++; ++ *(put++) = *ptr++; ++ *(put++) = *ptr++; ++ *(put++) = *ptr++; ++ } ++ else ++ { ++ escaped = !escaped; ++ if (!escaped && put) ++ *(put++) = '\\'; ++ ptr++; ++ } + break; + case '$': + if (escaped) diff --git a/SOURCES/0095-Fix-crash-on-http.patch b/SOURCES/0095-Fix-crash-on-http.patch new file mode 100644 index 0000000..a691528 --- /dev/null +++ b/SOURCES/0095-Fix-crash-on-http.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Gustavo Luiz Duarte +Date: Tue, 25 Sep 2012 18:40:55 -0400 +Subject: [PATCH] Fix crash on http + +Don't free file->data on receiving FIN flag since it is used all over without +checking. http_close() will be called later to free that memory. +https://bugzilla.redhat.com/show_bug.cgi?id=860834 +--- + grub-core/net/http.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/net/http.c b/grub-core/net/http.c +index 4684f8b333c..ef9538c539c 100644 +--- a/grub-core/net/http.c ++++ b/grub-core/net/http.c +@@ -393,7 +393,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial) + + data->sock = grub_net_tcp_open (file->device->net->server, + HTTP_PORT, http_receive, +- http_err, http_err, ++ http_err, NULL, + file); + if (!data->sock) + { diff --git a/SOURCES/0096-IBM-client-architecture-CAS-reboot-support.patch b/SOURCES/0096-IBM-client-architecture-CAS-reboot-support.patch new file mode 100644 index 0000000..1326fff --- /dev/null +++ b/SOURCES/0096-IBM-client-architecture-CAS-reboot-support.patch @@ -0,0 +1,171 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paulo Flabiano Smorigo +Date: Thu, 20 Sep 2012 18:07:39 -0300 +Subject: [PATCH] IBM client architecture (CAS) reboot support + +This is an implementation of IBM client architecture (CAS) reboot for GRUB. + +There are cases where the POWER firmware must reboot in order to support +specific features requested by a kernel. The kernel calls +ibm,client-architecture-support and it may either return or reboot with the new +feature set. eg: + +Calling ibm,client-architecture-support.../ +Elapsed time since release of system processors: 70959 mins 50 secs +Welcome to GRUB! + +Instead of return to the GRUB menu, it will check if the flag for CAS reboot is +set. If so, grub will automatically boot the last booted kernel using the same +parameters +--- + grub-core/kern/ieee1275/openfw.c | 62 ++++++++++++++++++++++++++++++++++++++++ + grub-core/normal/main.c | 19 ++++++++++++ + grub-core/script/execute.c | 7 +++++ + include/grub/ieee1275/ieee1275.h | 2 ++ + 4 files changed, 90 insertions(+) + +diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c +index ddb778340e4..6db8b986551 100644 +--- a/grub-core/kern/ieee1275/openfw.c ++++ b/grub-core/kern/ieee1275/openfw.c +@@ -561,3 +561,65 @@ grub_ieee1275_canonicalise_devname (const char *path) + return NULL; + } + ++/* Check if it's a CAS reboot. If so, set the script to be executed. */ ++int ++grub_ieee1275_cas_reboot (char *script) ++{ ++ grub_uint32_t ibm_ca_support_reboot; ++ grub_uint32_t ibm_fw_nbr_reboots; ++ char property_value[10]; ++ grub_ssize_t actual; ++ grub_ieee1275_ihandle_t options; ++ ++ if (grub_ieee1275_finddevice ("/options", &options) < 0) ++ return -1; ++ ++ /* Check two properties, one is enough to get cas reboot value */ ++ ibm_ca_support_reboot = 0; ++ if (grub_ieee1275_get_integer_property (grub_ieee1275_chosen, ++ "ibm,client-architecture-support-reboot", ++ &ibm_ca_support_reboot, ++ sizeof (ibm_ca_support_reboot), ++ &actual) >= 0) ++ grub_dprintf("ieee1275", "ibm,client-architecture-support-reboot: %u\n", ++ ibm_ca_support_reboot); ++ ++ ibm_fw_nbr_reboots = 0; ++ if (grub_ieee1275_get_property (options, "ibm,fw-nbr-reboots", ++ property_value, sizeof (property_value), ++ &actual) >= 0) ++ { ++ property_value[sizeof (property_value) - 1] = 0; ++ ibm_fw_nbr_reboots = (grub_uint8_t) grub_strtoul (property_value, 0, 10); ++ grub_dprintf("ieee1275", "ibm,fw-nbr-reboots: %u\n", ibm_fw_nbr_reboots); ++ } ++ ++ if (ibm_ca_support_reboot || ibm_fw_nbr_reboots) ++ { ++ if (! grub_ieee1275_get_property_length (options, "boot-last-label", &actual)) ++ { ++ if (actual > 1024) ++ script = grub_realloc (script, actual + 1); ++ grub_ieee1275_get_property (options, "boot-last-label", script, actual, ++ &actual); ++ return 0; ++ } ++ } ++ ++ grub_ieee1275_set_boot_last_label (""); ++ ++ return -1; ++} ++ ++int grub_ieee1275_set_boot_last_label (const char *text) ++{ ++ grub_ieee1275_ihandle_t options; ++ grub_ssize_t actual; ++ ++ grub_dprintf("ieee1275", "set boot_last_label (size: %u)\n", grub_strlen(text)); ++ if (! grub_ieee1275_finddevice ("/options", &options) && ++ options != (grub_ieee1275_ihandle_t) -1) ++ grub_ieee1275_set_property (options, "boot-last-label", text, ++ grub_strlen (text), &actual); ++ return 0; ++} +diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c +index 6f4970f71c1..f72844c9f37 100644 +--- a/grub-core/normal/main.c ++++ b/grub-core/normal/main.c +@@ -33,6 +33,9 @@ + #include + #include + #include ++#ifdef GRUB_MACHINE_IEEE1275 ++#include ++#endif + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -275,6 +278,22 @@ grub_normal_execute (const char *config, int nested, int batch) + { + menu = read_config_file (config); + ++#ifdef GRUB_MACHINE_IEEE1275 ++ int boot; ++ boot = 0; ++ char *script; ++ script = grub_malloc (1024); ++ if (! grub_ieee1275_cas_reboot (script)) ++ { ++ char *dummy[1] = { NULL }; ++ if (! grub_script_execute_sourcecode (script, 0, dummy)) ++ boot = 1; ++ } ++ grub_free (script); ++ if (boot) ++ grub_command_execute ("boot", 0, 0); ++#endif ++ + /* Ignore any error. */ + grub_errno = GRUB_ERR_NONE; + } +diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c +index 8f01c1bbfa2..cec9539a47c 100644 +--- a/grub-core/script/execute.c ++++ b/grub-core/script/execute.c +@@ -27,6 +27,9 @@ + #include + #include + #include ++#ifdef GRUB_MACHINE_IEEE1275 ++#include ++#endif + + /* Max digits for a char is 3 (0xFF is 255), similarly for an int it + is sizeof (int) * 3, and one extra for a possible -ve sign. */ +@@ -892,6 +895,10 @@ grub_script_execute_sourcecode (const char *source) + grub_err_t ret = 0; + struct grub_script *parsed_script; + ++#ifdef GRUB_MACHINE_IEEE1275 ++ grub_ieee1275_set_boot_last_label (source); ++#endif ++ + while (source) + { + char *line; +diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h +index 8e425130327..9f26c69a2df 100644 +--- a/include/grub/ieee1275/ieee1275.h ++++ b/include/grub/ieee1275/ieee1275.h +@@ -234,6 +234,8 @@ int EXPORT_FUNC(grub_ieee1275_devalias_next) (struct grub_ieee1275_devalias *ali + void EXPORT_FUNC(grub_ieee1275_children_peer) (struct grub_ieee1275_devalias *alias); + void EXPORT_FUNC(grub_ieee1275_children_first) (const char *devpath, + struct grub_ieee1275_devalias *alias); ++int EXPORT_FUNC(grub_ieee1275_cas_reboot) (char *script); ++int EXPORT_FUNC(grub_ieee1275_set_boot_last_label) (const char *text); + + #define FOR_IEEE1275_DEVALIASES(alias) for (grub_ieee1275_devalias_init_iterator (&(alias)); grub_ieee1275_devalias_next (&(alias));) + diff --git a/SOURCES/0097-Add-vlan-tag-support.patch b/SOURCES/0097-Add-vlan-tag-support.patch new file mode 100644 index 0000000..6181b62 --- /dev/null +++ b/SOURCES/0097-Add-vlan-tag-support.patch @@ -0,0 +1,183 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paulo Flabiano Smorigo +Date: Tue, 30 Oct 2012 15:19:39 -0200 +Subject: [PATCH] Add vlan-tag support + +This patch adds support for virtual LAN (VLAN) tagging. VLAN tagging allows +multiple VLANs in a bridged network to share the same physical network link but +maintain isolation: + +http://en.wikipedia.org/wiki/IEEE_802.1Q + +This patch should fix this bugzilla: +https://bugzilla.redhat.com/show_bug.cgi?id=871563 +--- + grub-core/kern/ieee1275/init.c | 1 + + grub-core/kern/ieee1275/openfw.c | 30 ++++++++++++++++++++++++++++ + grub-core/net/ethernet.c | 42 +++++++++++++++++++++++++++++++++++++--- + include/grub/ieee1275/ieee1275.h | 1 + + include/grub/net.h | 2 ++ + 5 files changed, 73 insertions(+), 3 deletions(-) + +diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c +index d5bd74d3552..8191f8cd658 100644 +--- a/grub-core/kern/ieee1275/init.c ++++ b/grub-core/kern/ieee1275/init.c +@@ -117,6 +117,7 @@ grub_machine_get_bootlocation (char **device, char **path) + char *dev, *canon; + char *ptr; + dev = grub_ieee1275_get_aliasdevname (bootpath); ++ grub_ieee1275_parse_net_options (bootpath); + canon = grub_ieee1275_canonicalise_devname (dev); + ptr = canon + grub_strlen (canon) - 1; + while (ptr > canon && (*ptr == ',' || *ptr == ':')) +diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c +index 6db8b986551..81276fae7b7 100644 +--- a/grub-core/kern/ieee1275/openfw.c ++++ b/grub-core/kern/ieee1275/openfw.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + enum grub_ieee1275_parse_type + { +@@ -451,6 +452,35 @@ fail: + return ret; + } + ++int ++grub_ieee1275_parse_net_options (const char *path) ++{ ++ char *comma; ++ char *args; ++ char *option = 0; ++ ++ args = grub_ieee1275_get_devargs (path); ++ if (!args) ++ /* There is no option. */ ++ return -1; ++ ++ do ++ { ++ comma = grub_strchr (args, ','); ++ if (! comma) ++ option = grub_strdup (args); ++ else ++ option = grub_strndup (args, (grub_size_t)(comma - args)); ++ args = comma + 1; ++ ++ if (! grub_strncmp(option, "vtag", 4)) ++ grub_env_set ("vlan-tag", option + grub_strlen("vtag=")); ++ ++ } while (comma); ++ ++ return 0; ++} ++ + char * + grub_ieee1275_get_device_type (const char *path) + { +diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c +index c397b1b348c..faaca67c50e 100644 +--- a/grub-core/net/ethernet.c ++++ b/grub-core/net/ethernet.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -56,10 +57,19 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, + { + struct etherhdr *eth; + grub_err_t err; ++ grub_uint32_t vlantag = 0; ++ grub_uint8_t etherhdr_size; + +- COMPILE_TIME_ASSERT (sizeof (*eth) < GRUB_NET_MAX_LINK_HEADER_SIZE); ++ etherhdr_size = sizeof (*eth); ++ COMPILE_TIME_ASSERT (sizeof (*eth) + 4 < GRUB_NET_MAX_LINK_HEADER_SIZE); + +- err = grub_netbuff_push (nb, sizeof (*eth)); ++ const char *vlantag_text = grub_env_get ("vlan-tag"); ++ if (vlantag_text != 0) { ++ etherhdr_size += 4; ++ vlantag = grub_strtoul (vlantag_text, 0, 16); ++ } ++ ++ err = grub_netbuff_push (nb, etherhdr_size); + if (err) + return err; + eth = (struct etherhdr *) nb->data; +@@ -76,6 +86,19 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, + return err; + inf->card->opened = 1; + } ++ ++ /* Check if a vlan-tag is needed. */ ++ if (vlantag != 0) ++ { ++ /* Move eth type to the right */ ++ grub_memcpy((char *) nb->data + etherhdr_size - 2, ++ (char *) nb->data + etherhdr_size - 6, 2); ++ ++ /* Add the tag in the middle */ ++ grub_memcpy((char *) nb->data + etherhdr_size - 6, ++ &vlantag, 4); ++ } ++ + return inf->card->driver->send (inf->card, nb); + } + +@@ -90,10 +113,23 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb, + grub_net_link_level_address_t hwaddress; + grub_net_link_level_address_t src_hwaddress; + grub_err_t err; ++ grub_uint8_t etherhdr_size = sizeof (*eth); ++ ++ grub_uint16_t vlantag_identifier = 0; ++ grub_memcpy (&vlantag_identifier, nb->data + etherhdr_size - 2, 2); ++ ++ /* Check if a vlan-tag is present. */ ++ if (vlantag_identifier == VLANTAG_IDENTIFIER) ++ { ++ etherhdr_size += 4; ++ /* Move eth type to the original position */ ++ grub_memcpy((char *) nb->data + etherhdr_size - 6, ++ (char *) nb->data + etherhdr_size - 2, 2); ++ } + + eth = (struct etherhdr *) nb->data; + type = grub_be_to_cpu16 (eth->type); +- err = grub_netbuff_pull (nb, sizeof (*eth)); ++ err = grub_netbuff_pull (nb, etherhdr_size); + if (err) + return err; + +diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h +index 9f26c69a2df..6a21f5d6de8 100644 +--- a/include/grub/ieee1275/ieee1275.h ++++ b/include/grub/ieee1275/ieee1275.h +@@ -236,6 +236,7 @@ void EXPORT_FUNC(grub_ieee1275_children_first) (const char *devpath, + struct grub_ieee1275_devalias *alias); + int EXPORT_FUNC(grub_ieee1275_cas_reboot) (char *script); + int EXPORT_FUNC(grub_ieee1275_set_boot_last_label) (const char *text); ++int EXPORT_FUNC(grub_ieee1275_parse_net_options) (const char *path); + + #define FOR_IEEE1275_DEVALIASES(alias) for (grub_ieee1275_devalias_init_iterator (&(alias)); grub_ieee1275_devalias_next (&(alias));) + +diff --git a/include/grub/net.h b/include/grub/net.h +index 538baa33eca..a799e6b8b69 100644 +--- a/include/grub/net.h ++++ b/include/grub/net.h +@@ -538,4 +538,6 @@ extern char *grub_net_default_server; + #define GRUB_NET_INTERVAL 400 + #define GRUB_NET_INTERVAL_ADDITION 20 + ++#define VLANTAG_IDENTIFIER 0x8100 ++ + #endif /* ! GRUB_NET_HEADER */ diff --git a/SOURCES/0098-Add-X-option-to-printf-functions.patch b/SOURCES/0098-Add-X-option-to-printf-functions.patch new file mode 100644 index 0000000..9631a38 --- /dev/null +++ b/SOURCES/0098-Add-X-option-to-printf-functions.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paulo Flabiano Smorigo +Date: Tue, 27 Nov 2012 16:58:39 -0200 +Subject: [PATCH] Add %X option to printf functions. + +--- + grub-core/kern/misc.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c +index c5c815d8d13..a56cfe78994 100644 +--- a/grub-core/kern/misc.c ++++ b/grub-core/kern/misc.c +@@ -762,7 +762,7 @@ __umoddi3 (grub_uint64_t a, grub_uint64_t b) + static inline char * + grub_lltoa (char *str, int c, unsigned long long n) + { +- unsigned base = (c == 'x') ? 16 : 10; ++ unsigned base = ((c == 'x') || (c == 'X')) ? 16 : 10; + char *p; + + if ((long long) n < 0 && c == 'd') +@@ -777,7 +777,7 @@ grub_lltoa (char *str, int c, unsigned long long n) + do + { + unsigned d = (unsigned) (n & 0xf); +- *p++ = (d > 9) ? d + 'a' - 10 : d + '0'; ++ *p++ = (d > 9) ? d + ((c == 'x') ? 'a' : 'A') - 10 : d + '0'; + } + while (n >>= 4); + else +@@ -850,6 +850,7 @@ parse_printf_args (const char *fmt0, struct printf_args *args, + { + case 'p': + case 'x': ++ case 'X': + case 'u': + case 'd': + case 'c': +@@ -930,6 +931,7 @@ parse_printf_args (const char *fmt0, struct printf_args *args, + switch (c) + { + case 'x': ++ case 'X': + case 'u': + args->ptr[curn].type = UNSIGNED_INT + longfmt; + break; +@@ -1067,6 +1069,7 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, + c = 'x'; + /* Fall through. */ + case 'x': ++ case 'X': + case 'u': + case 'd': + { diff --git a/SOURCES/0099-DHCP-client-ID-and-UUID-options-added.patch b/SOURCES/0099-DHCP-client-ID-and-UUID-options-added.patch new file mode 100644 index 0000000..16053af --- /dev/null +++ b/SOURCES/0099-DHCP-client-ID-and-UUID-options-added.patch @@ -0,0 +1,142 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paulo Flabiano Smorigo +Date: Tue, 27 Nov 2012 17:18:53 -0200 +Subject: [PATCH] DHCP client ID and UUID options added. + +--- + grub-core/net/bootp.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++----- + include/grub/net.h | 2 ++ + 2 files changed, 81 insertions(+), 8 deletions(-) + +diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c +index 6310ed447e8..88f20568914 100644 +--- a/grub-core/net/bootp.c ++++ b/grub-core/net/bootp.c +@@ -25,6 +25,49 @@ + #include + #include + ++static char * ++grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)), ++ const char *val __attribute__ ((unused))) ++{ ++ return NULL; ++} ++ ++static void ++set_env_limn_ro (const char *intername, const char *suffix, ++ const char *value, grub_size_t len) ++{ ++ char *varname, *varvalue; ++ char *ptr; ++ varname = grub_xasprintf ("net_%s_%s", intername, suffix); ++ if (!varname) ++ return; ++ for (ptr = varname; *ptr; ptr++) ++ if (*ptr == ':') ++ *ptr = '_'; ++ varvalue = grub_malloc (len + 1); ++ if (!varvalue) ++ { ++ grub_free (varname); ++ return; ++ } ++ ++ grub_memcpy (varvalue, value, len); ++ varvalue[len] = 0; ++ grub_env_set (varname, varvalue); ++ grub_register_variable_hook (varname, 0, grub_env_write_readonly); ++ grub_env_export (varname); ++ grub_free (varname); ++ grub_free (varvalue); ++} ++ ++static char ++hexdigit (grub_uint8_t val) ++{ ++ if (val < 10) ++ return val + '0'; ++ return val + 'a' - 10; ++} ++ + static void + parse_dhcp_vendor (const char *name, const void *vend, int limit, int *mask) + { +@@ -55,6 +98,9 @@ parse_dhcp_vendor (const char *name, const void *vend, int limit, int *mask) + + taglength = *ptr++; + ++ grub_dprintf("net", "DHCP option %u (0x%02x) found with length %u.\n", ++ tagtype, tagtype, taglength); ++ + switch (tagtype) + { + case GRUB_NET_BOOTP_NETMASK: +@@ -120,6 +166,39 @@ parse_dhcp_vendor (const char *name, const void *vend, int limit, int *mask) + taglength); + break; + ++ case GRUB_NET_BOOTP_CLIENT_ID: ++ set_env_limn_ro (name, "clientid", (char *) ptr, taglength); ++ break; ++ ++ case GRUB_NET_BOOTP_CLIENT_UUID: ++ { ++ if (taglength != 17) ++ break; ++ ++ /* The format is 9cfe245e-d0c8-bd45-a79f-54ea5fbd3d97 */ ++ ++ ptr += 1; ++ taglength -= 1; ++ ++ char *val = grub_malloc (2 * taglength + 4 + 1); ++ int i = 0; ++ int j = 0; ++ for (i = 0; i < taglength; i++) ++ { ++ val[2 * i + j] = hexdigit (ptr[i] >> 4); ++ val[2 * i + 1 + j] = hexdigit (ptr[i] & 0xf); ++ ++ if ((i == 3) || (i == 5) || (i == 7) || (i == 9)) ++ { ++ j++; ++ val[2 * i + 1+ j] = '-'; ++ } ++ } ++ ++ set_env_limn_ro (name, "clientuuid", (char *) val, 2 * taglength + 4); ++ } ++ break; ++ + /* If you need any other options please contact GRUB + development team. */ + } +@@ -288,14 +367,6 @@ grub_net_process_dhcp (struct grub_net_buff *nb, + } + } + +-static char +-hexdigit (grub_uint8_t val) +-{ +- if (val < 10) +- return val + '0'; +- return val + 'a' - 10; +-} +- + static grub_err_t + grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +diff --git a/include/grub/net.h b/include/grub/net.h +index a799e6b8b69..59e5975b11f 100644 +--- a/include/grub/net.h ++++ b/include/grub/net.h +@@ -433,6 +433,8 @@ enum + GRUB_NET_BOOTP_DOMAIN = 0x0f, + GRUB_NET_BOOTP_ROOT_PATH = 0x11, + GRUB_NET_BOOTP_EXTENSIONS_PATH = 0x12, ++ GRUB_NET_BOOTP_CLIENT_ID = 0x3d, ++ GRUB_NET_BOOTP_CLIENT_UUID = 0x61, + GRUB_NET_BOOTP_END = 0xff + }; + diff --git a/SOURCES/0100-Search-for-specific-config-file-for-netboot.patch b/SOURCES/0100-Search-for-specific-config-file-for-netboot.patch new file mode 100644 index 0000000..b72bea3 --- /dev/null +++ b/SOURCES/0100-Search-for-specific-config-file-for-netboot.patch @@ -0,0 +1,200 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paulo Flabiano Smorigo +Date: Tue, 27 Nov 2012 17:22:07 -0200 +Subject: [PATCH] Search for specific config file for netboot + +This patch implements a search for a specific configuration when the config +file is on a remoteserver. It uses the following order: + 1) DHCP client UUID option. + 2) MAC address (in lower case hexadecimal with dash separators); + 3) IP (in upper case hexadecimal) or IPv6; + 4) The original grub.cfg file. + +This procedure is similar to what is used by pxelinux and yaboot: +http://www.syslinux.org/wiki/index.php/PXELINUX#config + +This should close the bugzilla: +https://bugzilla.redhat.com/show_bug.cgi?id=873406 +--- + grub-core/net/net.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++ + grub-core/normal/main.c | 18 ++++++-- + include/grub/net.h | 3 ++ + 3 files changed, 135 insertions(+), 4 deletions(-) + +diff --git a/grub-core/net/net.c b/grub-core/net/net.c +index f2e723bd409..578e057e18f 100644 +--- a/grub-core/net/net.c ++++ b/grub-core/net/net.c +@@ -1702,6 +1702,124 @@ grub_net_restore_hw (void) + return GRUB_ERR_NONE; + } + ++grub_err_t ++grub_net_search_configfile (char *config) ++{ ++ grub_size_t config_len; ++ char *suffix; ++ ++ auto int search_through (grub_size_t num_tries, grub_size_t slice_size); ++ int search_through (grub_size_t num_tries, grub_size_t slice_size) ++ { ++ while (num_tries-- > 0) ++ { ++ grub_dprintf ("net", "probe %s\n", config); ++ ++ grub_file_t file; ++ file = grub_file_open (config); ++ ++ if (file) ++ { ++ grub_file_close (file); ++ grub_dprintf ("net", "found!\n"); ++ return 0; ++ } ++ else ++ { ++ if (grub_errno == GRUB_ERR_IO) ++ grub_errno = GRUB_ERR_NONE; ++ } ++ ++ if (grub_strlen (suffix) < slice_size) ++ break; ++ ++ config[grub_strlen (config) - slice_size] = '\0'; ++ } ++ ++ return 1; ++ } ++ ++ config_len = grub_strlen (config); ++ config[config_len] = '-'; ++ suffix = config + config_len + 1; ++ ++ struct grub_net_network_level_interface *inf; ++ FOR_NET_NETWORK_LEVEL_INTERFACES (inf) ++ { ++ /* By the Client UUID. */ ++ ++ char client_uuid_var[sizeof ("net_") + grub_strlen (inf->name) + ++ sizeof ("_clientuuid") + 1]; ++ grub_snprintf (client_uuid_var, sizeof (client_uuid_var), ++ "net_%s_clientuuid", inf->name); ++ ++ const char *client_uuid; ++ client_uuid = grub_env_get (client_uuid_var); ++ ++ if (client_uuid) ++ { ++ grub_strcpy (suffix, client_uuid); ++ if (search_through (1, 0) == 0) return GRUB_ERR_NONE; ++ } ++ ++ /* By the MAC address. */ ++ ++ /* Add ethernet type */ ++ grub_strcpy (suffix, "01-"); ++ ++ grub_net_hwaddr_to_str (&inf->hwaddress, suffix + 3); ++ ++ char *ptr; ++ for (ptr = suffix; *ptr; ptr++) ++ if (*ptr == ':') ++ *ptr = '-'; ++ ++ if (search_through (1, 0) == 0) return GRUB_ERR_NONE; ++ ++ /* By IP address */ ++ ++ switch ((&inf->address)->type) ++ { ++ case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: ++ { ++ grub_uint32_t n = grub_be_to_cpu32 ((&inf->address)->ipv4); ++ grub_snprintf (suffix, GRUB_NET_MAX_STR_ADDR_LEN, "%02X%02X%02X%02X", \ ++ ((n >> 24) & 0xff), ((n >> 16) & 0xff), \ ++ ((n >> 8) & 0xff), ((n >> 0) & 0xff)); ++ ++ if (search_through (8, 1) == 0) return GRUB_ERR_NONE; ++ break; ++ } ++ case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6: ++ { ++ char buf[GRUB_NET_MAX_STR_ADDR_LEN]; ++ struct grub_net_network_level_address base; ++ base.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; ++ grub_memcpy (&base.ipv6, ((&inf->address)->ipv6), 16); ++ grub_net_addr_to_str (&base, buf); ++ ++ for (ptr = buf; *ptr; ptr++) ++ if (*ptr == ':') ++ *ptr = '-'; ++ ++ grub_snprintf (suffix, GRUB_NET_MAX_STR_ADDR_LEN, "%s", buf); ++ if (search_through (1, 0) == 0) return GRUB_ERR_NONE; ++ break; ++ } ++ case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV: ++ return grub_error (GRUB_ERR_BUG, "shouldn't reach here"); ++ default: ++ return grub_error (GRUB_ERR_BUG, ++ "unsupported address type %d", (&inf->address)->type); ++ } ++ } ++ ++ /* Remove the remaining minus sign at the end. */ ++ config[config_len] = '\0'; ++ ++ return GRUB_ERR_NONE; ++} ++ + static struct grub_preboot *fini_hnd; + + static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; +diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c +index f72844c9f37..85d2a2862d4 100644 +--- a/grub-core/normal/main.c ++++ b/grub-core/normal/main.c +@@ -33,6 +33,7 @@ + #include + #include + #include ++#include + #ifdef GRUB_MACHINE_IEEE1275 + #include + #endif +@@ -365,10 +366,19 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), + + prefix = grub_env_get ("prefix"); + if (prefix) +- { +- config = grub_xasprintf ("%s/grub.cfg", prefix); +- if (! config) +- goto quit; ++ { ++ grub_size_t config_len; ++ config_len = grub_strlen (prefix) + ++ sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"); ++ config = grub_malloc (config_len); ++ ++ if (! config) ++ goto quit; ++ ++ grub_snprintf (config, config_len, "%s/grub.cfg", prefix); ++ ++ if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0) ++ grub_net_search_configfile (config); + + grub_enter_normal_mode (config); + grub_free (config); +diff --git a/include/grub/net.h b/include/grub/net.h +index 59e5975b11f..88fc71ceffe 100644 +--- a/include/grub/net.h ++++ b/include/grub/net.h +@@ -542,4 +542,7 @@ extern char *grub_net_default_server; + + #define VLANTAG_IDENTIFIER 0x8100 + ++grub_err_t ++grub_net_search_configfile (char *config); ++ + #endif /* ! GRUB_NET_HEADER */ diff --git a/SOURCES/0101-blscfg-add-blscfg-module-to-parse-Boot-Loader-Specif.patch b/SOURCES/0101-blscfg-add-blscfg-module-to-parse-Boot-Loader-Specif.patch new file mode 100644 index 0000000..9889d72 --- /dev/null +++ b/SOURCES/0101-blscfg-add-blscfg-module-to-parse-Boot-Loader-Specif.patch @@ -0,0 +1,248 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Fedora Ninjas +Date: Tue, 22 Jan 2013 06:31:38 +0100 +Subject: [PATCH] blscfg: add blscfg module to parse Boot Loader Specification + snippets + +http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec + +Works like this: + + insmod blscfg + bls_import + +Done! You should now have menu items for your snippets in place. + +Signed-off-by: Peter Jones +--- + grub-core/Makefile.core.def | 8 ++ + grub-core/commands/blscfg.c | 201 ++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 209 insertions(+) + create mode 100644 grub-core/commands/blscfg.c + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index ec46506e39e..7bf1c8a5880 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -746,6 +746,14 @@ module = { + common = commands/blocklist.c; + }; + ++module = { ++ name = blscfg; ++ common = commands/blscfg.c; ++ enable = i386_efi; ++ enable = x86_64_efi; ++ enable = i386_pc; ++}; ++ + module = { + name = boot; + common = commands/boot.c; +diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c +new file mode 100644 +index 00000000000..4274aca5a9d +--- /dev/null ++++ b/grub-core/commands/blscfg.c +@@ -0,0 +1,201 @@ ++/*-*- Mode: C; c-basic-offset: 2; indent-tabs-mode: t -*-*/ ++ ++/* bls.c - implementation of the boot loader spec */ ++ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++#ifdef GRUB_MACHINE_EFI ++#define GRUB_LINUX_CMD "linuxefi" ++#define GRUB_INITRD_CMD "initrdefi" ++#define GRUB_BLS_CONFIG_PATH "/EFI/fedora/loader/entries/" ++#define GRUB_BOOT_DEVICE "($boot)" ++#else ++#define GRUB_LINUX_CMD "linux" ++#define GRUB_INITRD_CMD "initrd" ++#define GRUB_BLS_CONFIG_PATH "/loader/entries/" ++#define GRUB_BOOT_DEVICE "($root)" ++#endif ++ ++static int parse_entry ( ++ const char *filename, ++ const struct grub_dirhook_info *info __attribute__ ((unused)), ++ void *data __attribute__ ((unused))) ++{ ++ grub_size_t n; ++ char *p; ++ grub_file_t f = NULL; ++ grub_off_t sz; ++ char *title = NULL, *options = NULL, *clinux = NULL, *initrd = NULL, *src = NULL; ++ const char *args[2] = { NULL, NULL }; ++ ++ if (filename[0] == '.') ++ return 0; ++ ++ n = grub_strlen (filename); ++ if (n <= 5) ++ return 0; ++ ++ if (grub_strcmp (filename + n - 5, ".conf") != 0) ++ return 0; ++ ++ p = grub_xasprintf (GRUB_BLS_CONFIG_PATH "%s", filename); ++ ++ f = grub_file_open (p); ++ if (!f) ++ goto finish; ++ ++ sz = grub_file_size (f); ++ if (sz == GRUB_FILE_SIZE_UNKNOWN || sz > 1024*1024) ++ goto finish; ++ ++ for (;;) ++ { ++ char *buf; ++ ++ buf = grub_file_getline (f); ++ if (!buf) ++ break; ++ ++ if (grub_strncmp (buf, "title ", 6) == 0) ++ { ++ grub_free (title); ++ title = grub_strdup (buf + 6); ++ if (!title) ++ goto finish; ++ } ++ else if (grub_strncmp (buf, "options ", 8) == 0) ++ { ++ grub_free (options); ++ options = grub_strdup (buf + 8); ++ if (!options) ++ goto finish; ++ } ++ else if (grub_strncmp (buf, "linux ", 6) == 0) ++ { ++ grub_free (clinux); ++ clinux = grub_strdup (buf + 6); ++ if (!clinux) ++ goto finish; ++ } ++ else if (grub_strncmp (buf, "initrd ", 7) == 0) ++ { ++ grub_free (initrd); ++ initrd = grub_strdup (buf + 7); ++ if (!initrd) ++ goto finish; ++ } ++ ++ grub_free(buf); ++ } ++ ++ if (!linux) ++ { ++ grub_printf ("Skipping file %s with no 'linux' key.", p); ++ goto finish; ++ } ++ ++ args[0] = title ? title : filename; ++ ++ src = grub_xasprintf ("load_video\n" ++ "set gfx_payload=keep\n" ++ "insmod gzio\n" ++ GRUB_LINUX_CMD " %s%s%s%s\n" ++ "%s%s%s%s", ++ GRUB_BOOT_DEVICE, clinux, options ? " " : "", options ? options : "", ++ initrd ? GRUB_INITRD_CMD " " : "", initrd ? GRUB_BOOT_DEVICE : "", initrd ? initrd : "", initrd ? "\n" : ""); ++ ++ grub_normal_add_menu_entry (1, args, NULL, NULL, "bls", NULL, NULL, src, 0); ++ ++finish: ++ grub_free (p); ++ grub_free (title); ++ grub_free (options); ++ grub_free (clinux); ++ grub_free (initrd); ++ grub_free (src); ++ ++ if (f) ++ grub_file_close (f); ++ ++ return 0; ++} ++ ++static grub_err_t ++grub_cmd_bls_import (grub_extcmd_context_t ctxt __attribute__ ((unused)), ++ int argc __attribute__ ((unused)), ++ char **args __attribute__ ((unused))) ++{ ++ grub_fs_t fs; ++ grub_device_t dev; ++ static grub_err_t r; ++ const char *devid; ++ ++ devid = grub_env_get ("root"); ++ if (!devid) ++ return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "root"); ++ ++ dev = grub_device_open (devid); ++ if (!dev) ++ return grub_errno; ++ ++ fs = grub_fs_probe (dev); ++ if (!fs) ++ { ++ r = grub_errno; ++ goto finish; ++ } ++ ++ r = fs->dir (dev, GRUB_BLS_CONFIG_PATH, parse_entry, NULL); ++ ++finish: ++ if (dev) ++ grub_device_close (dev); ++ ++ return r; ++} ++ ++static grub_extcmd_t cmd; ++ ++GRUB_MOD_INIT(bls) ++{ ++ cmd = grub_register_extcmd ("bls_import", ++ grub_cmd_bls_import, ++ 0, ++ NULL, ++ N_("Import Boot Loader Specification snippets."), ++ NULL); ++} ++ ++GRUB_MOD_FINI(bls) ++{ ++ grub_unregister_extcmd (cmd); ++} diff --git a/SOURCES/0102-Move-bash-completion-script-922997.patch b/SOURCES/0102-Move-bash-completion-script-922997.patch new file mode 100644 index 0000000..1da0068 --- /dev/null +++ b/SOURCES/0102-Move-bash-completion-script-922997.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 3 Apr 2013 14:35:34 -0400 +Subject: [PATCH] Move bash completion script (#922997) + +Apparently these go in a new place now. +--- + util/bash-completion.d/Makefile.am | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/util/bash-completion.d/Makefile.am b/util/bash-completion.d/Makefile.am +index 136287cf1bf..0bcdb060e84 100644 +--- a/util/bash-completion.d/Makefile.am ++++ b/util/bash-completion.d/Makefile.am +@@ -6,7 +6,7 @@ EXTRA_DIST = $(bash_completion_source) + + CLEANFILES = $(bash_completion_script) config.log + +-bashcompletiondir = $(sysconfdir)/bash_completion.d ++bashcompletiondir = $(datarootdir)/bash-completion/completions + bashcompletion_DATA = $(bash_completion_script) + + $(bash_completion_script): $(bash_completion_source) $(top_builddir)/config.status diff --git a/SOURCES/0103-for-ppc-reset-console-display-attr-when-clear-screen.patch b/SOURCES/0103-for-ppc-reset-console-display-attr-when-clear-screen.patch new file mode 100644 index 0000000..853c150 --- /dev/null +++ b/SOURCES/0103-for-ppc-reset-console-display-attr-when-clear-screen.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paulo Flabiano Smorigo +Date: Wed, 24 Apr 2013 10:51:48 -0300 +Subject: [PATCH] for ppc, reset console display attr when clear screen + +This should fix this bugzilla: +https://bugzilla.redhat.com/show_bug.cgi?id=908519 +--- + grub-core/term/terminfo.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/term/terminfo.c b/grub-core/term/terminfo.c +index f0d3e3debc6..7cb7909c8cf 100644 +--- a/grub-core/term/terminfo.c ++++ b/grub-core/term/terminfo.c +@@ -151,7 +151,7 @@ grub_terminfo_set_current (struct grub_term_output *term, + /* Clear the screen. Using serial console, screen(1) only recognizes the + * ANSI escape sequence. Using video console, Apple Open Firmware + * (version 3.1.1) only recognizes the literal ^L. So use both. */ +- data->cls = grub_strdup (" \e[2J"); ++ data->cls = grub_strdup (" \e[2J\e[m"); + data->reverse_video_on = grub_strdup ("\e[7m"); + data->reverse_video_off = grub_strdup ("\e[m"); + if (grub_strcmp ("ieee1275", str) == 0) diff --git a/SOURCES/0104-Don-t-write-messages-to-the-screen.patch b/SOURCES/0104-Don-t-write-messages-to-the-screen.patch new file mode 100644 index 0000000..c4d8945 --- /dev/null +++ b/SOURCES/0104-Don-t-write-messages-to-the-screen.patch @@ -0,0 +1,155 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Jon McCann +Date: Wed, 15 May 2013 13:30:20 -0400 +Subject: [PATCH] Don't write messages to the screen + +Writing messages to the screen before the menus or boot splash +happens so quickly it looks like something is wrong and isn't +very appealing. +--- + grub-core/gettext/gettext.c | 15 --------------- + grub-core/kern/main.c | 5 ----- + grub-core/boot/i386/pc/boot.S | 3 --- + grub-core/boot/i386/pc/diskboot.S | 5 ----- + util/grub.d/10_linux.in | 7 ------- + 5 files changed, 35 deletions(-) + +diff --git a/grub-core/gettext/gettext.c b/grub-core/gettext/gettext.c +index 4880cefe3f8..1e5c21d7ef2 100644 +--- a/grub-core/gettext/gettext.c ++++ b/grub-core/gettext/gettext.c +@@ -437,13 +437,9 @@ grub_gettext_env_write_lang (struct grub_env_var *var + grub_err_t err; + err = grub_gettext_init_ext (&main_context, val, grub_env_get ("locale_dir"), + grub_env_get ("prefix")); +- if (err) +- grub_print_error (); + + err = grub_gettext_init_ext (&secondary_context, val, + grub_env_get ("secondary_locale_dir"), 0); +- if (err) +- grub_print_error (); + + return grub_strdup (val); + } +@@ -455,8 +451,6 @@ grub_gettext_reread_prefix (const char *val) + err = grub_gettext_init_ext (&main_context, grub_env_get ("lang"), + grub_env_get ("locale_dir"), + val); +- if (err) +- grub_print_error (); + } + + static char * +@@ -466,8 +460,6 @@ read_main (struct grub_env_var *var + grub_err_t err; + err = grub_gettext_init_ext (&main_context, grub_env_get ("lang"), val, + grub_env_get ("prefix")); +- if (err) +- grub_print_error (); + return grub_strdup (val); + } + +@@ -478,9 +470,6 @@ read_secondary (struct grub_env_var *var + grub_err_t err; + err = grub_gettext_init_ext (&secondary_context, grub_env_get ("lang"), val, + 0); +- if (err) +- grub_print_error (); +- + return grub_strdup (val); + } + +@@ -506,12 +495,8 @@ GRUB_MOD_INIT (gettext) + + err = grub_gettext_init_ext (&main_context, lang, grub_env_get ("locale_dir"), + grub_env_get ("prefix")); +- if (err) +- grub_print_error (); + err = grub_gettext_init_ext (&secondary_context, lang, + grub_env_get ("secondary_locale_dir"), 0); +- if (err) +- grub_print_error (); + + grub_register_variable_hook ("locale_dir", NULL, read_main); + grub_register_variable_hook ("secondary_locale_dir", NULL, read_secondary); +diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c +index 8ab7794c47b..da47b18b50e 100644 +--- a/grub-core/kern/main.c ++++ b/grub-core/kern/main.c +@@ -268,11 +268,6 @@ grub_main (void) + + grub_boot_time ("After machine init."); + +- /* Hello. */ +- grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); +- grub_printf ("Welcome to GRUB!\n\n"); +- grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); +- + grub_load_config (); + + grub_boot_time ("Before loading embedded modules."); +diff --git a/grub-core/boot/i386/pc/boot.S b/grub-core/boot/i386/pc/boot.S +index b4975e2d029..432a472d529 100644 +--- a/grub-core/boot/i386/pc/boot.S ++++ b/grub-core/boot/i386/pc/boot.S +@@ -249,9 +249,6 @@ real_start: + /* save drive reference first thing! */ + pushw %dx + +- /* print a notification message on the screen */ +- MSG(notification_string) +- + /* set %si to the disk address packet */ + movw $disk_address_packet, %si + +diff --git a/grub-core/boot/i386/pc/diskboot.S b/grub-core/boot/i386/pc/diskboot.S +index d030a14c916..a494d029c61 100644 +--- a/grub-core/boot/i386/pc/diskboot.S ++++ b/grub-core/boot/i386/pc/diskboot.S +@@ -50,11 +50,6 @@ _start: + /* save drive reference first thing! */ + pushw %dx + +- /* print a notification message on the screen */ +- pushw %si +- MSG(notification_string) +- popw %si +- + /* this sets up for the first run through "bootloop" */ + movw $LOCAL(firstlist), %di + +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index ad34cc02d36..e762e1f4e37 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -126,29 +126,22 @@ linux_entry () + fi + printf '%s\n' "${prepare_boot_cache}" | sed "s/^/$submenu_indentation/" + fi +- message="$(gettext_printf "Loading Linux %s ..." ${version})" + if [ -d /sys/firmware/efi ]; then + sed "s/^/$submenu_indentation/" << EOF +- echo '$(echo "$message" | grub_quote)' + linuxefi ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args} + EOF + else + sed "s/^/$submenu_indentation/" << EOF +- echo '$(echo "$message" | grub_quote)' + linux ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args} + EOF + fi + if test -n "${initrd}" ; then +- # TRANSLATORS: ramdisk isn't identifier. Should be translated. +- message="$(gettext_printf "Loading initial ramdisk ...")" + if [ -d /sys/firmware/efi ]; then + sed "s/^/$submenu_indentation/" << EOF +- echo '$(echo "$message" | grub_quote)' + initrdefi ${rel_dirname}/${initrd} + EOF + else + sed "s/^/$submenu_indentation/" << EOF +- echo '$message' + initrd ${rel_dirname}/${initrd} + EOF + fi diff --git a/SOURCES/0105-Don-t-print-GNU-GRUB-header.patch b/SOURCES/0105-Don-t-print-GNU-GRUB-header.patch new file mode 100644 index 0000000..2ee1c91 --- /dev/null +++ b/SOURCES/0105-Don-t-print-GNU-GRUB-header.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Jon McCann +Date: Wed, 15 May 2013 13:53:48 -0400 +Subject: [PATCH] Don't print GNU GRUB header + +No one cares. +--- + grub-core/normal/main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c +index 85d2a2862d4..3777cd22ce3 100644 +--- a/grub-core/normal/main.c ++++ b/grub-core/normal/main.c +@@ -212,6 +212,7 @@ grub_normal_init_page (struct grub_term_output *term, + + grub_term_cls (term); + ++#if 0 + msg_formatted = grub_xasprintf (_("GNU GRUB version %s"), PACKAGE_VERSION); + if (!msg_formatted) + return; +@@ -235,6 +236,7 @@ grub_normal_init_page (struct grub_term_output *term, + grub_putcode ('\n', term); + grub_putcode ('\n', term); + grub_free (unicode_msg); ++#endif + } + + static void diff --git a/SOURCES/0106-Don-t-add-to-highlighted-row.patch b/SOURCES/0106-Don-t-add-to-highlighted-row.patch new file mode 100644 index 0000000..ef6dc25 --- /dev/null +++ b/SOURCES/0106-Don-t-add-to-highlighted-row.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Jon McCann +Date: Wed, 15 May 2013 17:49:45 -0400 +Subject: [PATCH] Don't add '*' to highlighted row + +It is already highlighted. +--- + grub-core/normal/menu_text.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c +index 2ff294101d8..2f84fccb6fe 100644 +--- a/grub-core/normal/menu_text.c ++++ b/grub-core/normal/menu_text.c +@@ -242,7 +242,7 @@ print_entry (int y, int highlight, grub_menu_entry_t entry, + unicode_title[i] = ' '; + + if (data->geo.num_entries > 1) +- grub_putcode (highlight ? '*' : ' ', data->term); ++ grub_putcode (' ', data->term); + + grub_print_ucs4_menu (unicode_title, + unicode_title + len, diff --git a/SOURCES/0107-Message-string-cleanups.patch b/SOURCES/0107-Message-string-cleanups.patch new file mode 100644 index 0000000..42502c1 --- /dev/null +++ b/SOURCES/0107-Message-string-cleanups.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Jon McCann +Date: Fri, 7 Jun 2013 11:09:04 -0400 +Subject: [PATCH] Message string cleanups + +Make use of terminology consistent. Remove jargon. +--- + grub-core/normal/menu_text.c | 21 +++++++++------------ + 1 file changed, 9 insertions(+), 12 deletions(-) + +diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c +index 2f84fccb6fe..9d20c6b85b2 100644 +--- a/grub-core/normal/menu_text.c ++++ b/grub-core/normal/menu_text.c +@@ -157,9 +157,8 @@ print_message (int nested, int edit, struct grub_term_output *term, int dry_run) + + if (edit) + { +- ret += grub_print_message_indented_real (_("Minimum Emacs-like screen editing is \ +-supported. TAB lists completions. Press Ctrl-x or F10 to boot, Ctrl-c or F2 for a \ +-command-line or ESC to discard edits and return to the GRUB menu."), ++ ret += grub_print_message_indented_real (_("Press Ctrl-x or F10 to start, Ctrl-c or F2 for a \ ++command prompt or Escape to discard edits and return to the menu. Pressing Tab lists possible completions."), + STANDARD_MARGIN, STANDARD_MARGIN, + term, dry_run); + } +@@ -167,8 +166,8 @@ command-line or ESC to discard edits and return to the GRUB menu."), + { + char *msg_translated; + +- msg_translated = grub_xasprintf (_("Use the %C and %C keys to select which " +- "entry is highlighted."), ++ msg_translated = grub_xasprintf (_("Use the %C and %C keys to change the " ++ "selection."), + GRUB_UNICODE_UPARROW, + GRUB_UNICODE_DOWNARROW); + if (!msg_translated) +@@ -181,17 +180,15 @@ command-line or ESC to discard edits and return to the GRUB menu."), + if (nested) + { + ret += grub_print_message_indented_real +- (_("Press enter to boot the selected OS, " +- "`e' to edit the commands before booting " +- "or `c' for a command-line. ESC to return previous menu."), ++ (_("Press 'e' to edit the selected item, " ++ "or 'c' for a command prompt. Press Escape to return to the previous menu."), + STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run); + } + else + { + ret += grub_print_message_indented_real +- (_("Press enter to boot the selected OS, " +- "`e' to edit the commands before booting " +- "or `c' for a command-line."), ++ (_("Press 'e' to edit the selected item, " ++ "or 'c' for a command prompt."), + STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run); + } + } +@@ -440,7 +437,7 @@ menu_text_print_timeout (int timeout, void *dataptr) + || data->timeout_msg == TIMEOUT_TERSE_NO_MARGIN) + msg_translated = grub_xasprintf (_("%ds"), timeout); + else +- msg_translated = grub_xasprintf (_("The highlighted entry will be executed automatically in %ds."), timeout); ++ msg_translated = grub_xasprintf (_("The selected entry will be started automatically in %ds."), timeout); + if (!msg_translated) + { + grub_print_error (); diff --git a/SOURCES/0108-Fix-border-spacing-now-that-we-aren-t-displaying-it.patch b/SOURCES/0108-Fix-border-spacing-now-that-we-aren-t-displaying-it.patch new file mode 100644 index 0000000..0c1a9ab --- /dev/null +++ b/SOURCES/0108-Fix-border-spacing-now-that-we-aren-t-displaying-it.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Jon McCann +Date: Fri, 7 Jun 2013 14:08:23 -0400 +Subject: [PATCH] Fix border spacing now that we aren't displaying it + +--- + grub-core/normal/menu_text.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c +index 9d20c6b85b2..aa3454ff525 100644 +--- a/grub-core/normal/menu_text.c ++++ b/grub-core/normal/menu_text.c +@@ -331,12 +331,12 @@ grub_menu_init_page (int nested, int edit, + int empty_lines = 1; + int version_msg = 1; + +- geo->border = 1; +- geo->first_entry_x = 1 /* margin */ + 1 /* border */; ++ geo->border = 0; ++ geo->first_entry_x = 0 /* margin */ + 0 /* border */; + geo->entry_width = grub_term_width (term) - 5; + + geo->first_entry_y = 2 /* two empty lines*/ +- + 1 /* GNU GRUB version text */ + 1 /* top border */; ++ + 0 /* GNU GRUB version text */ + 1 /* top border */; + + geo->timeout_lines = 2; + diff --git a/SOURCES/0109-Use-the-correct-indentation-for-the-term-help-text.patch b/SOURCES/0109-Use-the-correct-indentation-for-the-term-help-text.patch new file mode 100644 index 0000000..cbeb9fd --- /dev/null +++ b/SOURCES/0109-Use-the-correct-indentation-for-the-term-help-text.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Jon McCann +Date: Fri, 7 Jun 2013 14:08:49 -0400 +Subject: [PATCH] Use the correct indentation for the term help text + +That is consistent with the menu help text +--- + grub-core/normal/main.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c +index 3777cd22ce3..0da2a520d2d 100644 +--- a/grub-core/normal/main.c ++++ b/grub-core/normal/main.c +@@ -426,8 +426,8 @@ grub_normal_reader_init (int nested) + grub_normal_init_page (term, 1); + grub_term_setcursor (term, 1); + +- if (grub_term_width (term) > 3 + STANDARD_MARGIN + 20) +- grub_print_message_indented (msg_formatted, 3, STANDARD_MARGIN, term); ++ if (grub_term_width (term) > 2 * STANDARD_MARGIN + 20) ++ grub_print_message_indented (msg_formatted, STANDARD_MARGIN, STANDARD_MARGIN, term); + else + grub_print_message_indented (msg_formatted, 0, 0, term); + grub_putcode ('\n', term); diff --git a/SOURCES/0110-Indent-menu-entries.patch b/SOURCES/0110-Indent-menu-entries.patch new file mode 100644 index 0000000..98c3b7d --- /dev/null +++ b/SOURCES/0110-Indent-menu-entries.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Jon McCann +Date: Fri, 7 Jun 2013 14:30:55 -0400 +Subject: [PATCH] Indent menu entries + +--- + grub-core/normal/menu_text.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c +index aa3454ff525..01b6f1c739f 100644 +--- a/grub-core/normal/menu_text.c ++++ b/grub-core/normal/menu_text.c +@@ -239,7 +239,8 @@ print_entry (int y, int highlight, grub_menu_entry_t entry, + unicode_title[i] = ' '; + + if (data->geo.num_entries > 1) +- grub_putcode (' ', data->term); ++ for (i = 0; i < STANDARD_MARGIN; i++) ++ grub_putcode (' ', data->term); + + grub_print_ucs4_menu (unicode_title, + unicode_title + len, diff --git a/SOURCES/0111-Fix-margins.patch b/SOURCES/0111-Fix-margins.patch new file mode 100644 index 0000000..5c5ae10 --- /dev/null +++ b/SOURCES/0111-Fix-margins.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Jon McCann +Date: Fri, 7 Jun 2013 14:59:36 -0400 +Subject: [PATCH] Fix margins + +--- + grub-core/normal/menu_text.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c +index 01b6f1c739f..ead3391b7bb 100644 +--- a/grub-core/normal/menu_text.c ++++ b/grub-core/normal/menu_text.c +@@ -333,17 +333,15 @@ grub_menu_init_page (int nested, int edit, + int version_msg = 1; + + geo->border = 0; +- geo->first_entry_x = 0 /* margin */ + 0 /* border */; +- geo->entry_width = grub_term_width (term) - 5; ++ geo->first_entry_x = 0; /* no margin */ ++ geo->entry_width = grub_term_width (term) - 1; + +- geo->first_entry_y = 2 /* two empty lines*/ +- + 0 /* GNU GRUB version text */ + 1 /* top border */; ++ geo->first_entry_y = 3; /* three empty lines*/ + + geo->timeout_lines = 2; + + /* 3 lines for timeout message and bottom margin. 2 lines for the border. */ + geo->num_entries = grub_term_height (term) - geo->first_entry_y +- - 1 /* bottom border */ + - 1 /* empty line before info message*/ + - geo->timeout_lines /* timeout */ + - 1 /* empty final line */; diff --git a/SOURCES/0112-Add-support-for-UEFI-operating-systems-returned-by-o.patch b/SOURCES/0112-Add-support-for-UEFI-operating-systems-returned-by-o.patch new file mode 100644 index 0000000..f093824 --- /dev/null +++ b/SOURCES/0112-Add-support-for-UEFI-operating-systems-returned-by-o.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Wed, 12 Jun 2013 11:51:49 -0400 +Subject: [PATCH] Add support for UEFI operating systems returned by os-prober + +os-prober returns UEFI operating systems in the form: + +path:long-name:name + +where path is the path under the EFI directory on the ESP. This is in +contrast to legacy OSes, where path is the device string. Handle this case. +--- + util/grub.d/30_os-prober.in | 22 ++++++++++++++++++---- + 1 file changed, 18 insertions(+), 4 deletions(-) + +diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in +index 6f38c82a554..9f955abb788 100644 +--- a/util/grub.d/30_os-prober.in ++++ b/util/grub.d/30_os-prober.in +@@ -322,9 +322,23 @@ EOF + EOF + ;; + *) +- echo -n " " +- # TRANSLATORS: %s is replaced by OS name. +- gettext_printf "%s is not yet supported by grub-mkconfig.\n" "${LONGNAME}" >&2 +- ;; ++ case ${DEVICE} in ++ *.efi) ++ cat << EOF ++menuentry '$(echo "${LONGNAME}" | grub_quote)' { ++EOF ++ save_default_entry | grub_add_tab ++ cat << EOF ++ chainloader /EFI/${DEVICE} ++ boot ++} ++EOF ++ ;; ++ *) ++ echo -n " " ++ # TRANSLATORS: %s is replaced by OS name. ++ gettext_printf "%s is not yet supported by grub-mkconfig.\n" "${LONGNAME}" >&2 ++ ;; ++ esac + esac + done diff --git a/SOURCES/0113-Disable-GRUB-video-support-for-IBM-power-machines.patch b/SOURCES/0113-Disable-GRUB-video-support-for-IBM-power-machines.patch new file mode 100644 index 0000000..32f4c3a --- /dev/null +++ b/SOURCES/0113-Disable-GRUB-video-support-for-IBM-power-machines.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paulo Flabiano Smorigo +Date: Tue, 11 Jun 2013 15:14:05 -0300 +Subject: [PATCH] Disable GRUB video support for IBM power machines + +Should fix the problem in bugzilla: +https://bugzilla.redhat.com/show_bug.cgi?id=973205 +--- + grub-core/kern/ieee1275/cmain.c | 5 ++++- + grub-core/video/ieee1275.c | 9 ++++++--- + include/grub/ieee1275/ieee1275.h | 2 ++ + 3 files changed, 12 insertions(+), 4 deletions(-) + +diff --git a/grub-core/kern/ieee1275/cmain.c b/grub-core/kern/ieee1275/cmain.c +index 3e12e6b24e1..3e14f539368 100644 +--- a/grub-core/kern/ieee1275/cmain.c ++++ b/grub-core/kern/ieee1275/cmain.c +@@ -90,7 +90,10 @@ grub_ieee1275_find_options (void) + } + + if (rc >= 0 && grub_strncmp (tmp, "IBM", 3) == 0) +- grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS); ++ { ++ grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS); ++ grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_DISABLE_VIDEO_SUPPORT); ++ } + + /* Old Macs have no key repeat, newer ones have fully working one. + The ones inbetween when repeated key generates an escaoe sequence +diff --git a/grub-core/video/ieee1275.c b/grub-core/video/ieee1275.c +index 0b150ec2406..813ab38e1e0 100644 +--- a/grub-core/video/ieee1275.c ++++ b/grub-core/video/ieee1275.c +@@ -351,9 +351,12 @@ static struct grub_video_adapter grub_video_ieee1275_adapter = + + GRUB_MOD_INIT(ieee1275_fb) + { +- find_display (); +- if (display) +- grub_video_register (&grub_video_ieee1275_adapter); ++ if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_DISABLE_VIDEO_SUPPORT)) ++ { ++ find_display (); ++ if (display) ++ grub_video_register (&grub_video_ieee1275_adapter); ++ } + } + + GRUB_MOD_FINI(ieee1275_fb) +diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h +index 6a21f5d6de8..663935da7a5 100644 +--- a/include/grub/ieee1275/ieee1275.h ++++ b/include/grub/ieee1275/ieee1275.h +@@ -146,6 +146,8 @@ enum grub_ieee1275_flag + GRUB_IEEE1275_FLAG_BROKEN_REPEAT, + + GRUB_IEEE1275_FLAG_CURSORONOFF_ANSI_BROKEN, ++ ++ GRUB_IEEE1275_FLAG_DISABLE_VIDEO_SUPPORT + }; + + extern int EXPORT_FUNC(grub_ieee1275_test_flag) (enum grub_ieee1275_flag flag); diff --git a/SOURCES/0114-Use-2-instead-of-1-for-our-right-hand-margin-so-line.patch b/SOURCES/0114-Use-2-instead-of-1-for-our-right-hand-margin-so-line.patch new file mode 100644 index 0000000..2f81996 --- /dev/null +++ b/SOURCES/0114-Use-2-instead-of-1-for-our-right-hand-margin-so-line.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 21 Jun 2013 14:44:08 -0400 +Subject: [PATCH] Use -2 instead of -1 for our right-hand margin, so + linewrapping works (#976643). + +Signed-off-by: Peter Jones +--- + grub-core/normal/menu_text.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c +index ead3391b7bb..bc1fc718fc0 100644 +--- a/grub-core/normal/menu_text.c ++++ b/grub-core/normal/menu_text.c +@@ -334,7 +334,7 @@ grub_menu_init_page (int nested, int edit, + + geo->border = 0; + geo->first_entry_x = 0; /* no margin */ +- geo->entry_width = grub_term_width (term) - 1; ++ geo->entry_width = grub_term_width (term) - 2; + + geo->first_entry_y = 3; /* three empty lines*/ + diff --git a/SOURCES/0115-Use-linux16-when-appropriate-880840.patch b/SOURCES/0115-Use-linux16-when-appropriate-880840.patch new file mode 100644 index 0000000..2bbab63 --- /dev/null +++ b/SOURCES/0115-Use-linux16-when-appropriate-880840.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 28 Oct 2013 10:05:07 -0400 +Subject: [PATCH] Use linux16 when appropriate (#880840) + +The kernel group really would prefer that we use the 16 bit entry point +on x86 bios machines. + +Resolves: rhbz#880840 + +Signed-off-by: Peter Jones +--- + util/grub.d/10_linux.in | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index e762e1f4e37..600bfd29dc7 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -74,6 +74,11 @@ linux_entry () + type="$3" + args="$4" + ++ sixteenbit="" ++ case "$machine" in ++ i?86|x86_64) sixteenbit="16" ;; ++ esac ++ + if [ -z "$boot_device_id" ]; then + boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")" + fi +@@ -132,7 +137,7 @@ linux_entry () + EOF + else + sed "s/^/$submenu_indentation/" << EOF +- linux ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args} ++ linux${sixteenbit} ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args} + EOF + fi + if test -n "${initrd}" ; then +@@ -142,7 +147,7 @@ EOF + EOF + else + sed "s/^/$submenu_indentation/" << EOF +- initrd ${rel_dirname}/${initrd} ++ initrd${sixteenbit} ${rel_dirname}/${initrd} + EOF + fi + fi diff --git a/SOURCES/0116-Enable-pager-by-default.-985860.patch b/SOURCES/0116-Enable-pager-by-default.-985860.patch new file mode 100644 index 0000000..8c545b7 --- /dev/null +++ b/SOURCES/0116-Enable-pager-by-default.-985860.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 28 Oct 2013 10:09:27 -0400 +Subject: [PATCH] Enable pager by default. (#985860) + +Signed-off-by: Peter Jones +--- + util/grub.d/00_header.in | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in +index ce2ec819d8c..fefa7ddfcc0 100644 +--- a/util/grub.d/00_header.in ++++ b/util/grub.d/00_header.in +@@ -43,6 +43,8 @@ if [ "x${GRUB_DEFAULT_BUTTON}" = "xsaved" ] ; then GRUB_DEFAULT_BUTTON='${saved_ + if [ "x${GRUB_TIMEOUT_BUTTON}" = "x" ] ; then GRUB_TIMEOUT_BUTTON="$GRUB_TIMEOUT" ; fi + + cat << EOF ++set pager=1 ++ + if [ -s \$prefix/grubenv ]; then + load_env + fi diff --git a/SOURCES/0117-F10-doesn-t-work-on-serial-so-don-t-tell-the-user-to.patch b/SOURCES/0117-F10-doesn-t-work-on-serial-so-don-t-tell-the-user-to.patch new file mode 100644 index 0000000..82f00d6 --- /dev/null +++ b/SOURCES/0117-F10-doesn-t-work-on-serial-so-don-t-tell-the-user-to.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 28 Oct 2013 10:13:27 -0400 +Subject: [PATCH] F10 doesn't work on serial, so don't tell the user to hit it + (#987443) + +Signed-off-by: Peter Jones +--- + grub-core/normal/menu_text.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c +index bc1fc718fc0..6202c2a16c9 100644 +--- a/grub-core/normal/menu_text.c ++++ b/grub-core/normal/menu_text.c +@@ -157,7 +157,7 @@ print_message (int nested, int edit, struct grub_term_output *term, int dry_run) + + if (edit) + { +- ret += grub_print_message_indented_real (_("Press Ctrl-x or F10 to start, Ctrl-c or F2 for a \ ++ ret += grub_print_message_indented_real (_("Press Ctrl-x to start, Ctrl-c for a \ + command prompt or Escape to discard edits and return to the menu. Pressing Tab lists possible completions."), + STANDARD_MARGIN, STANDARD_MARGIN, + term, dry_run); diff --git a/SOURCES/0118-Don-t-say-GNU-Linux-in-generated-menus.patch b/SOURCES/0118-Don-t-say-GNU-Linux-in-generated-menus.patch new file mode 100644 index 0000000..9210b89 --- /dev/null +++ b/SOURCES/0118-Don-t-say-GNU-Linux-in-generated-menus.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 14 Mar 2011 14:27:42 -0400 +Subject: [PATCH] Don't say "GNU/Linux" in generated menus. + +--- + util/grub.d/10_linux.in | 4 ++-- + util/grub.d/20_linux_xen.in | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index 600bfd29dc7..c943a1e403e 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -29,9 +29,9 @@ export TEXTDOMAINDIR="@localedir@" + CLASS="--class gnu-linux --class gnu --class os" + + if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then +- OS=GNU/Linux ++ OS="$(sed 's, release .*$,,g' /etc/system-release)" + else +- OS="${GRUB_DISTRIBUTOR} GNU/Linux" ++ OS="${GRUB_DISTRIBUTOR}" + CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1|LC_ALL=C sed 's,[^[:alnum:]_],_,g') ${CLASS}" + fi + +diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in +index a60843500ed..79d4e38d643 100644 +--- a/util/grub.d/20_linux_xen.in ++++ b/util/grub.d/20_linux_xen.in +@@ -29,9 +29,9 @@ export TEXTDOMAINDIR="@localedir@" + CLASS="--class gnu-linux --class gnu --class os --class xen" + + if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then +- OS=GNU/Linux ++ OS="$(sed 's, release .*$,,g' /etc/system-release)" + else +- OS="${GRUB_DISTRIBUTOR} GNU/Linux" ++ OS="${GRUB_DISTRIBUTOR}" + CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1|LC_ALL=C sed 's,[^[:alnum:]_],_,g') ${CLASS}" + fi + diff --git a/SOURCES/0119-Don-t-draw-a-border-around-the-menu.patch b/SOURCES/0119-Don-t-draw-a-border-around-the-menu.patch new file mode 100644 index 0000000..409c472 --- /dev/null +++ b/SOURCES/0119-Don-t-draw-a-border-around-the-menu.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Jon McCann +Date: Wed, 15 May 2013 16:47:33 -0400 +Subject: [PATCH] Don't draw a border around the menu + +It looks cleaner without it. +--- + grub-core/normal/menu_text.c | 43 ------------------------------------------- + 1 file changed, 43 deletions(-) + +diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c +index 6202c2a16c9..beddd7f81c1 100644 +--- a/grub-core/normal/menu_text.c ++++ b/grub-core/normal/menu_text.c +@@ -108,47 +108,6 @@ grub_print_message_indented (const char *msg, int margin_left, int margin_right, + grub_print_message_indented_real (msg, margin_left, margin_right, term, 0); + } + +-static void +-draw_border (struct grub_term_output *term, const struct grub_term_screen_geometry *geo) +-{ +- int i; +- +- grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL); +- +- grub_term_gotoxy (term, (struct grub_term_coordinate) { geo->first_entry_x - 1, +- geo->first_entry_y - 1 }); +- grub_putcode (GRUB_UNICODE_CORNER_UL, term); +- for (i = 0; i < geo->entry_width + 1; i++) +- grub_putcode (GRUB_UNICODE_HLINE, term); +- grub_putcode (GRUB_UNICODE_CORNER_UR, term); +- +- for (i = 0; i < geo->num_entries; i++) +- { +- grub_term_gotoxy (term, (struct grub_term_coordinate) { geo->first_entry_x - 1, +- geo->first_entry_y + i }); +- grub_putcode (GRUB_UNICODE_VLINE, term); +- grub_term_gotoxy (term, +- (struct grub_term_coordinate) { geo->first_entry_x + geo->entry_width + 1, +- geo->first_entry_y + i }); +- grub_putcode (GRUB_UNICODE_VLINE, term); +- } +- +- grub_term_gotoxy (term, +- (struct grub_term_coordinate) { geo->first_entry_x - 1, +- geo->first_entry_y - 1 + geo->num_entries + 1 }); +- grub_putcode (GRUB_UNICODE_CORNER_LL, term); +- for (i = 0; i < geo->entry_width + 1; i++) +- grub_putcode (GRUB_UNICODE_HLINE, term); +- grub_putcode (GRUB_UNICODE_CORNER_LR, term); +- +- grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL); +- +- grub_term_gotoxy (term, +- (struct grub_term_coordinate) { geo->first_entry_x - 1, +- (geo->first_entry_y - 1 + geo->num_entries +- + GRUB_TERM_MARGIN + 1) }); +-} +- + static int + print_message (int nested, int edit, struct grub_term_output *term, int dry_run) + { +@@ -403,8 +362,6 @@ grub_menu_init_page (int nested, int edit, + + grub_term_normal_color = grub_color_menu_normal; + grub_term_highlight_color = grub_color_menu_highlight; +- if (geo->border) +- draw_border (term, geo); + grub_term_normal_color = old_color_normal; + grub_term_highlight_color = old_color_highlight; + geo->timeout_y = geo->first_entry_y + geo->num_entries diff --git a/SOURCES/0120-Use-the-standard-margin-for-the-timeout-string.patch b/SOURCES/0120-Use-the-standard-margin-for-the-timeout-string.patch new file mode 100644 index 0000000..046af91 --- /dev/null +++ b/SOURCES/0120-Use-the-standard-margin-for-the-timeout-string.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Jon McCann +Date: Fri, 7 Jun 2013 10:52:32 -0400 +Subject: [PATCH] Use the standard margin for the timeout string + +So that it aligns with the other messages +--- + grub-core/normal/menu_text.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c +index beddd7f81c1..33b208bcf44 100644 +--- a/grub-core/normal/menu_text.c ++++ b/grub-core/normal/menu_text.c +@@ -369,7 +369,7 @@ grub_menu_init_page (int nested, int edit, + if (bottom_message) + { + grub_term_gotoxy (term, +- (struct grub_term_coordinate) { GRUB_TERM_MARGIN, ++ (struct grub_term_coordinate) { STANDARD_MARGIN, + geo->timeout_y }); + + print_message (nested, edit, term, 0); +@@ -404,14 +404,14 @@ menu_text_print_timeout (int timeout, void *dataptr) + if (data->timeout_msg == TIMEOUT_UNKNOWN) + { + data->timeout_msg = grub_print_message_indented_real (msg_translated, +- 3, 1, data->term, 1) ++ STANDARD_MARGIN, 1, data->term, 1) + <= data->geo.timeout_lines ? TIMEOUT_NORMAL : TIMEOUT_TERSE; + if (data->timeout_msg == TIMEOUT_TERSE) + { + grub_free (msg_translated); + msg_translated = grub_xasprintf (_("%ds"), timeout); + if (grub_term_width (data->term) < 10) +- data->timeout_msg = TIMEOUT_TERSE_NO_MARGIN; ++ data->timeout_msg = STANDARD_MARGIN; + } + } + diff --git a/SOURCES/0121-Fix-grub_script_execute_sourcecode-usage-on-ppc.patch b/SOURCES/0121-Fix-grub_script_execute_sourcecode-usage-on-ppc.patch new file mode 100644 index 0000000..d4d88d2 --- /dev/null +++ b/SOURCES/0121-Fix-grub_script_execute_sourcecode-usage-on-ppc.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 10 Jan 2014 09:36:24 -0500 +Subject: [PATCH] Fix grub_script_execute_sourcecode() usage on ppc. + +593e430c made it not take the extra argc/argv that this code still +passes it. + +Signed-off-by: Peter Jones +--- + grub-core/normal/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c +index 0da2a520d2d..f66c03c4c6e 100644 +--- a/grub-core/normal/main.c ++++ b/grub-core/normal/main.c +@@ -289,7 +289,7 @@ grub_normal_execute (const char *config, int nested, int batch) + if (! grub_ieee1275_cas_reboot (script)) + { + char *dummy[1] = { NULL }; +- if (! grub_script_execute_sourcecode (script, 0, dummy)) ++ if (! grub_script_execute_sourcecode (script)) + boot = 1; + } + grub_free (script); diff --git a/SOURCES/0122-Add-.eh_frame-to-list-of-relocations-stripped.patch b/SOURCES/0122-Add-.eh_frame-to-list-of-relocations-stripped.patch new file mode 100644 index 0000000..68d6089 --- /dev/null +++ b/SOURCES/0122-Add-.eh_frame-to-list-of-relocations-stripped.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Fedora Ninjas +Date: Mon, 13 Jan 2014 21:50:59 -0500 +Subject: [PATCH] Add .eh_frame to list of relocations stripped + +--- + conf/Makefile.common | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/conf/Makefile.common b/conf/Makefile.common +index e4c301fb6b6..6f836d82771 100644 +--- a/conf/Makefile.common ++++ b/conf/Makefile.common +@@ -45,7 +45,7 @@ CFLAGS_KERNEL = $(CFLAGS_CPU) $(CFLAGS_PLATFORM) -ffreestanding + LDFLAGS_KERNEL = $(LDFLAGS_CPU) $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) $(TARGET_LDFLAGS_STATIC_LIBGCC) + CPPFLAGS_KERNEL = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) -DGRUB_KERNEL=1 + CCASFLAGS_KERNEL = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) +-STRIPFLAGS_KERNEL = -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version ++STRIPFLAGS_KERNEL = -R .eh_frame -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version + + CFLAGS_MODULE = $(CFLAGS_CPU) $(CFLAGS_PLATFORM) -ffreestanding + LDFLAGS_MODULE = $(LDFLAGS_CPU) $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-r,-d diff --git a/SOURCES/0123-Make-10_linux-work-with-our-changes-for-linux16-and-.patch b/SOURCES/0123-Make-10_linux-work-with-our-changes-for-linux16-and-.patch new file mode 100644 index 0000000..8b30f95 --- /dev/null +++ b/SOURCES/0123-Make-10_linux-work-with-our-changes-for-linux16-and-.patch @@ -0,0 +1,82 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 14 Jan 2014 13:12:23 -0500 +Subject: [PATCH] Make 10_linux work with our changes for linux16 and linuxefi + on aarch64 + +Signed-off-by: Peter Jones +--- + util/grub.d/10_linux.in | 31 ++++++++++++++++++++++++++++--- + 1 file changed, 28 insertions(+), 3 deletions(-) + +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index c943a1e403e..2b8c561ff7b 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -75,8 +75,18 @@ linux_entry () + args="$4" + + sixteenbit="" ++ linuxefi="linux" ++ initrdefi="initrd" + case "$machine" in +- i?86|x86_64) sixteenbit="16" ;; ++ i?86|x86_64) ++ sixteenbit="16" ++ linuxefi="linuxefi" ++ initrdefi="initrdefi" ++ ;; ++ aarch64) ++ linuxefi="linux" ++ initrdefi="initrd" ++ ;; + esac + + if [ -z "$boot_device_id" ]; then +@@ -133,7 +143,7 @@ linux_entry () + fi + if [ -d /sys/firmware/efi ]; then + sed "s/^/$submenu_indentation/" << EOF +- linuxefi ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args} ++ ${linuxefi} ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args} + EOF + else + sed "s/^/$submenu_indentation/" << EOF +@@ -143,7 +153,7 @@ EOF + if test -n "${initrd}" ; then + if [ -d /sys/firmware/efi ]; then + sed "s/^/$submenu_indentation/" << EOF +- initrdefi ${rel_dirname}/${initrd} ++ ${initrdefi} ${rel_dirname}/${initrd} + EOF + else + sed "s/^/$submenu_indentation/" << EOF +@@ -151,6 +161,13 @@ EOF + EOF + fi + fi ++ if test -n "${fdt}" ; then ++ message="$(gettext_printf "Loading fdt ...")" ++ sed "s/^/$submenu_indentation/" << EOF ++ echo '$(echo "$message" | grub_quote)' ++ devicetree ${rel_dirname}/${fdt} ++EOF ++ fi + sed "s/^/$submenu_indentation/" << EOF + } + EOF +@@ -211,6 +228,14 @@ while [ "x$list" != "x" ] ; do + fi + done + ++ fdt= ++ for i in "dtb-${version}" "dtb-${alt_version}"; do ++ if test -e "${dirname}/${i}/foundation-v8.dtb" ; then ++ fdt="${i}/foundation-v8.dtb" ++ break ++ fi ++ done ++ + config= + for i in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "/etc/kernels/kernel-config-${version}" ; do + if test -e "${i}" ; then diff --git a/SOURCES/0124-Don-t-print-during-fdt-loading-method.patch b/SOURCES/0124-Don-t-print-during-fdt-loading-method.patch new file mode 100644 index 0000000..d826d5e --- /dev/null +++ b/SOURCES/0124-Don-t-print-during-fdt-loading-method.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 14 Jan 2014 16:15:46 -0500 +Subject: [PATCH] Don't print during fdt loading method. + +Signed-off-by: Peter Jones +--- + util/grub.d/10_linux.in | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index 2b8c561ff7b..acf2e0e2d37 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -162,9 +162,7 @@ EOF + fi + fi + if test -n "${fdt}" ; then +- message="$(gettext_printf "Loading fdt ...")" + sed "s/^/$submenu_indentation/" << EOF +- echo '$(echo "$message" | grub_quote)' + devicetree ${rel_dirname}/${fdt} + EOF + fi diff --git a/SOURCES/0125-Honor-a-symlink-when-generating-configuration-by-gru.patch b/SOURCES/0125-Honor-a-symlink-when-generating-configuration-by-gru.patch new file mode 100644 index 0000000..36735ab --- /dev/null +++ b/SOURCES/0125-Honor-a-symlink-when-generating-configuration-by-gru.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Marcel Kolaja +Date: Tue, 21 Jan 2014 10:57:08 -0500 +Subject: [PATCH] Honor a symlink when generating configuration by + grub2-mkconfig + +Honor a symlink when generating configuration by grub2-mkconfig, so that +the -o option follows it rather than overwriting it with a regular file. +--- + util/grub-mkconfig.in | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in +index ca040dd776c..b00f9e61f40 100644 +--- a/util/grub-mkconfig.in ++++ b/util/grub-mkconfig.in +@@ -272,7 +272,8 @@ and /etc/grub.d/* files or please file a bug report with + echo >&2 + else + # none of the children aborted with error, install the new grub.cfg +- mv -f ${grub_cfg}.new ${grub_cfg} ++ cat ${grub_cfg}.new > ${grub_cfg} ++ rm -f ${grub_cfg}.new + fi + fi + diff --git a/SOURCES/0126-Don-t-munge-raw-spaces-when-we-re-doing-our-cmdline-.patch b/SOURCES/0126-Don-t-munge-raw-spaces-when-we-re-doing-our-cmdline-.patch new file mode 100644 index 0000000..33bdad2 --- /dev/null +++ b/SOURCES/0126-Don-t-munge-raw-spaces-when-we-re-doing-our-cmdline-.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 30 Jun 2014 14:16:46 -0400 +Subject: [PATCH] Don't munge raw spaces when we're doing our cmdline escaping + (#923374) + +Signed-off-by: Peter Jones +--- + grub-core/lib/cmdline.c | 11 +---------- + 1 file changed, 1 insertion(+), 10 deletions(-) + +diff --git a/grub-core/lib/cmdline.c b/grub-core/lib/cmdline.c +index 0a5b2afb94b..970ea868c14 100644 +--- a/grub-core/lib/cmdline.c ++++ b/grub-core/lib/cmdline.c +@@ -97,16 +97,7 @@ int grub_create_loader_cmdline (int argc, char *argv[], char *buf, + + while (*c) + { +- if (*c == ' ') +- { +- *buf++ = '\\'; +- *buf++ = 'x'; +- *buf++ = '2'; +- *buf++ = '0'; +- c++; +- continue; +- } +- else if (*c == '\\' && *(c+1) == 'x' && ++ if (*c == '\\' && *(c+1) == 'x' && + is_hex(*(c+2)) && is_hex(*(c+3))) + { + *buf++ = *c++; diff --git a/SOURCES/0127-Don-t-require-a-password-to-boot-entries-generated-b.patch b/SOURCES/0127-Don-t-require-a-password-to-boot-entries-generated-b.patch new file mode 100644 index 0000000..f907ad8 --- /dev/null +++ b/SOURCES/0127-Don-t-require-a-password-to-boot-entries-generated-b.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 11 Feb 2014 11:14:50 -0500 +Subject: [PATCH] Don't require a password to boot entries generated by + grub-mkconfig. + +When we set a password, we just want that to mean you can't /edit/ an entry. + +Resolves: rhbz#1030176 + +Signed-off-by: Peter Jones +--- + util/grub.d/10_linux.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index acf2e0e2d37..136abd7a6e3 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -26,7 +26,7 @@ datarootdir="@datarootdir@" + export TEXTDOMAIN=@PACKAGE@ + export TEXTDOMAINDIR="@localedir@" + +-CLASS="--class gnu-linux --class gnu --class os" ++CLASS="--class gnu-linux --class gnu --class os --unrestricted" + + if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then + OS="$(sed 's, release .*$,,g' /etc/system-release)" diff --git a/SOURCES/0128-Don-t-emit-Booting-.-message.patch b/SOURCES/0128-Don-t-emit-Booting-.-message.patch new file mode 100644 index 0000000..a39e7b2 --- /dev/null +++ b/SOURCES/0128-Don-t-emit-Booting-.-message.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 18 Feb 2014 09:37:49 -0500 +Subject: [PATCH] Don't emit "Booting ..." message. + +UI team still hates this stuff, so we're disabling it for RHEL 7. + +Resolves: rhbz#1023142 + +Signed-off-by: Peter Jones +--- + grub-core/normal/menu.c | 2 ++ + grub-core/normal/menu_entry.c | 3 --- + 2 files changed, 2 insertions(+), 3 deletions(-) + +diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c +index b47991ababa..cc27c370776 100644 +--- a/grub-core/normal/menu.c ++++ b/grub-core/normal/menu.c +@@ -810,9 +810,11 @@ static void + notify_booting (grub_menu_entry_t entry, + void *userdata __attribute__((unused))) + { ++#if 0 + grub_printf (" "); + grub_printf_ (N_("Booting `%s'"), entry->title); + grub_printf ("\n\n"); ++#endif + } + + /* Callback invoked when a default menu entry executed because of a timeout +diff --git a/grub-core/normal/menu_entry.c b/grub-core/normal/menu_entry.c +index b485df82122..62e5db1fef8 100644 +--- a/grub-core/normal/menu_entry.c ++++ b/grub-core/normal/menu_entry.c +@@ -1156,9 +1156,6 @@ run (struct screen *screen) + char *dummy[1] = { NULL }; + + grub_cls (); +- grub_printf (" "); +- grub_printf_ (N_("Booting a command list")); +- grub_printf ("\n\n"); + + errs_before = grub_err_printed_errors; + diff --git a/SOURCES/0129-Make-CTRL-and-ALT-keys-work-as-expected-on-EFI-syste.patch b/SOURCES/0129-Make-CTRL-and-ALT-keys-work-as-expected-on-EFI-syste.patch new file mode 100644 index 0000000..140c207 --- /dev/null +++ b/SOURCES/0129-Make-CTRL-and-ALT-keys-work-as-expected-on-EFI-syste.patch @@ -0,0 +1,301 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 3 Feb 2014 15:21:46 -0500 +Subject: [PATCH] Make CTRL and ALT keys work as expected on EFI systems + (version 5). + +This is version 4. + +Changes from version 1: +- handles SHIFT as a modifier +- handles F11 and F12 keys +- uses the handle provided by the system table to find our _EX protocol. + +Changes from version 2: +- eliminate duplicate keycode translation. + +Changes from version 3: +- Do not add the shift modifier for any ascii character between space + (0x20) and DEL (0x7f); the combination of the modifier and many of the + keys causes it not to be recognized at all. Specifically, if we + include the modifier on any querty punctuation character, i.e. + anything the string "~!@#$%^&*()_+{}|:\"<>?" represents in C, it stops + being recognized whatsoever. + +Changes from version 4: +- Always initialize term->data from locate protocol (i.e. make it + unconditional.) + +Signed-off-by: Peter Jones +--- + grub-core/term/efi/console.c | 118 +++++++++++++++++++++++++++++++++++-------- + include/grub/efi/api.h | 65 +++++++++++++++++++++++- + 2 files changed, 161 insertions(+), 22 deletions(-) + +diff --git a/grub-core/term/efi/console.c b/grub-core/term/efi/console.c +index a37eb841c72..677eab5820f 100644 +--- a/grub-core/term/efi/console.c ++++ b/grub-core/term/efi/console.c +@@ -104,26 +104,12 @@ const unsigned efi_codes[] = + GRUB_TERM_KEY_DC, GRUB_TERM_KEY_PPAGE, GRUB_TERM_KEY_NPAGE, GRUB_TERM_KEY_F1, + GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3, GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5, + GRUB_TERM_KEY_F6, GRUB_TERM_KEY_F7, GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9, +- GRUB_TERM_KEY_F10, 0, 0, '\e' ++ GRUB_TERM_KEY_F10, GRUB_TERM_KEY_F10, GRUB_TERM_KEY_F11, '\e' + }; + +- + static int +-grub_console_getkey (struct grub_term_input *term __attribute__ ((unused))) ++grub_efi_translate_key (grub_efi_input_key_t key) + { +- grub_efi_simple_input_interface_t *i; +- grub_efi_input_key_t key; +- grub_efi_status_t status; +- +- if (grub_efi_is_finished) +- return 0; +- +- i = grub_efi_system_table->con_in; +- status = efi_call_2 (i->read_key_stroke, i, &key); +- +- if (status != GRUB_EFI_SUCCESS) +- return GRUB_TERM_NO_KEY; +- + if (key.scan_code == 0) + { + /* Some firmware implementations use VT100-style codes against the spec. +@@ -139,9 +125,98 @@ grub_console_getkey (struct grub_term_input *term __attribute__ ((unused))) + else if (key.scan_code < ARRAY_SIZE (efi_codes)) + return efi_codes[key.scan_code]; + ++ if (key.unicode_char >= 0x20 && key.unicode_char <= 0x7f) ++ return key.unicode_char; ++ + return GRUB_TERM_NO_KEY; + } + ++static int ++grub_console_getkey_con (struct grub_term_input *term __attribute__ ((unused))) ++{ ++ grub_efi_simple_input_interface_t *i; ++ grub_efi_input_key_t key; ++ grub_efi_status_t status; ++ ++ i = grub_efi_system_table->con_in; ++ status = efi_call_2 (i->read_key_stroke, i, &key); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ return GRUB_TERM_NO_KEY; ++ ++ return grub_efi_translate_key(key); ++} ++ ++static int ++grub_console_getkey_ex(struct grub_term_input *term) ++{ ++ grub_efi_key_data_t key_data; ++ grub_efi_status_t status; ++ grub_efi_uint32_t kss; ++ int key = -1; ++ ++ grub_efi_simple_text_input_ex_interface_t *text_input = term->data; ++ ++ status = efi_call_2 (text_input->read_key_stroke, text_input, &key_data); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ return GRUB_TERM_NO_KEY; ++ ++ kss = key_data.key_state.key_shift_state; ++ key = grub_efi_translate_key(key_data.key); ++ ++ if (key == GRUB_TERM_NO_KEY) ++ return GRUB_TERM_NO_KEY; ++ ++ if (kss & GRUB_EFI_SHIFT_STATE_VALID) ++ { ++ if ((kss & GRUB_EFI_LEFT_SHIFT_PRESSED ++ || kss & GRUB_EFI_RIGHT_SHIFT_PRESSED) ++ && !(key >= 0x20 && key <= 0x7f)) ++ key |= GRUB_TERM_SHIFT; ++ if (kss & GRUB_EFI_LEFT_ALT_PRESSED || kss & GRUB_EFI_RIGHT_ALT_PRESSED) ++ key |= GRUB_TERM_ALT; ++ if (kss & GRUB_EFI_LEFT_CONTROL_PRESSED ++ || kss & GRUB_EFI_RIGHT_CONTROL_PRESSED) ++ key |= GRUB_TERM_CTRL; ++ } ++ ++ return key; ++} ++ ++static grub_err_t ++grub_efi_console_input_init (struct grub_term_input *term) ++{ ++ grub_efi_guid_t text_input_ex_guid = ++ GRUB_EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID; ++ ++ if (grub_efi_is_finished) ++ return 0; ++ ++ grub_efi_simple_text_input_ex_interface_t *text_input = term->data; ++ if (text_input) ++ return 0; ++ ++ text_input = grub_efi_open_protocol(grub_efi_system_table->console_in_handler, ++ &text_input_ex_guid, ++ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); ++ term->data = (void *)text_input; ++ ++ return 0; ++} ++ ++static int ++grub_console_getkey (struct grub_term_input *term) ++{ ++ if (grub_efi_is_finished) ++ return 0; ++ ++ if (term->data) ++ return grub_console_getkey_ex(term); ++ else ++ return grub_console_getkey_con(term); ++} ++ + static struct grub_term_coordinate + grub_console_getwh (struct grub_term_output *term __attribute__ ((unused))) + { +@@ -243,7 +318,7 @@ grub_console_setcursor (struct grub_term_output *term __attribute__ ((unused)), + } + + static grub_err_t +-grub_efi_console_init (struct grub_term_output *term) ++grub_efi_console_output_init (struct grub_term_output *term) + { + grub_efi_set_text_mode (1); + grub_console_setcursor (term, 1); +@@ -251,7 +326,7 @@ grub_efi_console_init (struct grub_term_output *term) + } + + static grub_err_t +-grub_efi_console_fini (struct grub_term_output *term) ++grub_efi_console_output_fini (struct grub_term_output *term) + { + grub_console_setcursor (term, 0); + grub_efi_set_text_mode (0); +@@ -262,13 +337,14 @@ static struct grub_term_input grub_console_term_input = + { + .name = "console", + .getkey = grub_console_getkey, ++ .init = grub_efi_console_input_init, + }; + + static struct grub_term_output grub_console_term_output = + { + .name = "console", +- .init = grub_efi_console_init, +- .fini = grub_efi_console_fini, ++ .init = grub_efi_console_output_init, ++ .fini = grub_efi_console_output_fini, + .putchar = grub_console_putchar, + .getwh = grub_console_getwh, + .getxy = grub_console_getxy, +@@ -291,8 +367,8 @@ grub_console_init (void) + return; + } + +- grub_term_register_input ("console", &grub_console_term_input); + grub_term_register_output ("console", &grub_console_term_output); ++ grub_term_register_input ("console", &grub_console_term_input); + } + + void +diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h +index e5dd543a801..142340372e1 100644 +--- a/include/grub/efi/api.h ++++ b/include/grub/efi/api.h +@@ -111,7 +111,7 @@ + { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +-#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \ ++#define GRUB_EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \ + { 0xdd9e7534, 0x7762, 0x4698, \ + { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } \ + } +@@ -952,6 +952,32 @@ struct grub_efi_input_key + }; + typedef struct grub_efi_input_key grub_efi_input_key_t; + ++typedef grub_efi_uint8_t grub_efi_key_toggle_state_t; ++struct grub_efi_key_state ++{ ++ grub_efi_uint32_t key_shift_state; ++ grub_efi_key_toggle_state_t key_toggle_state; ++}; ++typedef struct grub_efi_key_state grub_efi_key_state_t; ++ ++#define GRUB_EFI_SHIFT_STATE_VALID 0x80000000 ++#define GRUB_EFI_RIGHT_SHIFT_PRESSED 0x00000001 ++#define GRUB_EFI_LEFT_SHIFT_PRESSED 0x00000002 ++#define GRUB_EFI_RIGHT_CONTROL_PRESSED 0x00000004 ++#define GRUB_EFI_LEFT_CONTROL_PRESSED 0x00000008 ++#define GRUB_EFI_RIGHT_ALT_PRESSED 0x00000010 ++#define GRUB_EFI_LEFT_ALT_PRESSED 0x00000020 ++#define GRUB_EFI_RIGHT_LOGO_PRESSED 0x00000040 ++#define GRUB_EFI_LEFT_LOGO_PRESSED 0x00000080 ++#define GRUB_EFI_MENU_KEY_PRESSED 0x00000100 ++#define GRUB_EFI_SYS_REQ_PRESSED 0x00000200 ++ ++#define GRUB_EFI_TOGGLE_STATE_VALID 0x80 ++#define GRUB_EFI_KEY_STATE_EXPOSED 0x40 ++#define GRUB_EFI_SCROLL_LOCK_ACTIVE 0x01 ++#define GRUB_EFI_NUM_LOCK_ACTIVE 0x02 ++#define GRUB_EFI_CAPS_LOCK_ACTIVE 0x04 ++ + struct grub_efi_simple_text_output_mode + { + grub_efi_int32_t max_mode; +@@ -1294,6 +1320,43 @@ struct grub_efi_simple_input_interface + }; + typedef struct grub_efi_simple_input_interface grub_efi_simple_input_interface_t; + ++struct grub_efi_key_data { ++ grub_efi_input_key_t key; ++ grub_efi_key_state_t key_state; ++}; ++typedef struct grub_efi_key_data grub_efi_key_data_t; ++ ++typedef grub_efi_status_t (*grub_efi_key_notify_function_t) ( ++ grub_efi_key_data_t *key_data ++ ); ++ ++struct grub_efi_simple_text_input_ex_interface ++{ ++ grub_efi_status_t ++ (*reset) (struct grub_efi_simple_text_input_ex_interface *this, ++ grub_efi_boolean_t extended_verification); ++ ++ grub_efi_status_t ++ (*read_key_stroke) (struct grub_efi_simple_text_input_ex_interface *this, ++ grub_efi_key_data_t *key_data); ++ ++ grub_efi_event_t wait_for_key; ++ ++ grub_efi_status_t ++ (*set_state) (struct grub_efi_simple_text_input_ex_interface *this, ++ grub_efi_key_toggle_state_t *key_toggle_state); ++ ++ grub_efi_status_t ++ (*register_key_notify) (struct grub_efi_simple_text_input_ex_interface *this, ++ grub_efi_key_data_t *key_data, ++ grub_efi_key_notify_function_t key_notification_function); ++ ++ grub_efi_status_t ++ (*unregister_key_notify) (struct grub_efi_simple_text_input_ex_interface *this, ++ void *notification_handle); ++}; ++typedef struct grub_efi_simple_text_input_ex_interface grub_efi_simple_text_input_ex_interface_t; ++ + struct grub_efi_simple_text_output_interface + { + grub_efi_status_t diff --git a/SOURCES/0130-May-as-well-try-it.patch b/SOURCES/0130-May-as-well-try-it.patch new file mode 100644 index 0000000..73d2b16 --- /dev/null +++ b/SOURCES/0130-May-as-well-try-it.patch @@ -0,0 +1,1959 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 4 Mar 2014 11:00:23 -0500 +Subject: [PATCH] May as well try it. + +--- + configure.ac | 23 ++++++ + conf/Makefile.extra-dist | 1 - + docs/Makefile.am | 2 - + docs/man/grub-bios-setup.h2m | 6 -- + docs/man/grub-editenv.h2m | 5 -- + docs/man/grub-emu.h2m | 6 -- + docs/man/grub-file.h2m | 2 - + docs/man/grub-fstest.h2m | 4 - + docs/man/grub-glue-efi.h2m | 4 - + docs/man/grub-install.h2m | 6 -- + docs/man/grub-kbdcomp.h2m | 10 --- + docs/man/grub-macbless.h2m | 4 - + docs/man/grub-macho2img.h2m | 4 - + docs/man/grub-menulst2cfg.h2m | 4 - + docs/man/grub-mkconfig.h2m | 4 - + docs/man/grub-mkfont.h2m | 4 - + docs/man/grub-mkimage.h2m | 6 -- + docs/man/grub-mklayout.h2m | 10 --- + docs/man/grub-mknetdir.h2m | 4 - + docs/man/grub-mkpasswd-pbkdf2.h2m | 4 - + docs/man/grub-mkrelpath.h2m | 4 - + docs/man/grub-mkrescue.h2m | 4 - + docs/man/grub-mkstandalone.h2m | 4 - + docs/man/grub-mount.h2m | 2 - + docs/man/grub-ofpathname.h2m | 4 - + docs/man/grub-pe2elf.h2m | 4 - + docs/man/grub-probe.h2m | 4 - + docs/man/grub-reboot.h2m | 5 -- + docs/man/grub-render-label.h2m | 3 - + docs/man/grub-script-check.h2m | 4 - + docs/man/grub-set-default.h2m | 5 -- + docs/man/grub-sparc64-setup.h2m | 6 -- + docs/man/grub-syslinux2cfg.h2m | 4 - + gentpl.py | 5 +- + util/grub-bios-setup.8 | 54 +++++++++++++ + util/grub-editenv.1 | 46 +++++++++++ + util/grub-file.1 | 165 ++++++++++++++++++++++++++++++++++++++ + util/grub-fstest.1 | 99 +++++++++++++++++++++++ + util/grub-glue-efi.1 | 31 +++++++ + util/grub-install.8 | 129 +++++++++++++++++++++++++++++ + util/grub-kbdcomp.1 | 19 +++++ + util/grub-macbless.1 | 22 +++++ + util/grub-menulst2cfg.1 | 12 +++ + util/grub-mkconfig.8 | 17 ++++ + util/grub-mkfont.1 | 87 ++++++++++++++++++++ + util/grub-mkimage.1 | 95 ++++++++++++++++++++++ + util/grub-mklayout.1 | 27 +++++++ + util/grub-mknetdir.1 | 12 +++ + util/grub-mkpasswd-pbkdf2.1 | 27 +++++++ + util/grub-mkrelpath.1 | 12 +++ + util/grub-mkrescue.1 | 123 ++++++++++++++++++++++++++++ + util/grub-mkstandalone.1 | 100 +++++++++++++++++++++++ + util/grub-ofpathname.8 | 12 +++ + util/grub-probe.8 | 80 ++++++++++++++++++ + util/grub-reboot.8 | 21 +++++ + util/grub-render-label.1 | 51 ++++++++++++ + util/grub-script-check.1 | 21 +++++ + util/grub-set-default.8 | 21 +++++ + util/grub-sparc64-setup.8 | 12 +++ + 59 files changed, 1319 insertions(+), 147 deletions(-) + delete mode 100644 docs/man/grub-bios-setup.h2m + delete mode 100644 docs/man/grub-editenv.h2m + delete mode 100644 docs/man/grub-emu.h2m + delete mode 100644 docs/man/grub-file.h2m + delete mode 100644 docs/man/grub-fstest.h2m + delete mode 100644 docs/man/grub-glue-efi.h2m + delete mode 100644 docs/man/grub-install.h2m + delete mode 100644 docs/man/grub-kbdcomp.h2m + delete mode 100644 docs/man/grub-macbless.h2m + delete mode 100644 docs/man/grub-macho2img.h2m + delete mode 100644 docs/man/grub-menulst2cfg.h2m + delete mode 100644 docs/man/grub-mkconfig.h2m + delete mode 100644 docs/man/grub-mkfont.h2m + delete mode 100644 docs/man/grub-mkimage.h2m + delete mode 100644 docs/man/grub-mklayout.h2m + delete mode 100644 docs/man/grub-mknetdir.h2m + delete mode 100644 docs/man/grub-mkpasswd-pbkdf2.h2m + delete mode 100644 docs/man/grub-mkrelpath.h2m + delete mode 100644 docs/man/grub-mkrescue.h2m + delete mode 100644 docs/man/grub-mkstandalone.h2m + delete mode 100644 docs/man/grub-mount.h2m + delete mode 100644 docs/man/grub-ofpathname.h2m + delete mode 100644 docs/man/grub-pe2elf.h2m + delete mode 100644 docs/man/grub-probe.h2m + delete mode 100644 docs/man/grub-reboot.h2m + delete mode 100644 docs/man/grub-render-label.h2m + delete mode 100644 docs/man/grub-script-check.h2m + delete mode 100644 docs/man/grub-set-default.h2m + delete mode 100644 docs/man/grub-sparc64-setup.h2m + delete mode 100644 docs/man/grub-syslinux2cfg.h2m + create mode 100644 util/grub-bios-setup.8 + create mode 100644 util/grub-editenv.1 + create mode 100644 util/grub-file.1 + create mode 100644 util/grub-fstest.1 + create mode 100644 util/grub-glue-efi.1 + create mode 100644 util/grub-install.8 + create mode 100644 util/grub-kbdcomp.1 + create mode 100644 util/grub-macbless.1 + create mode 100644 util/grub-menulst2cfg.1 + create mode 100644 util/grub-mkconfig.8 + create mode 100644 util/grub-mkfont.1 + create mode 100644 util/grub-mkimage.1 + create mode 100644 util/grub-mklayout.1 + create mode 100644 util/grub-mknetdir.1 + create mode 100644 util/grub-mkpasswd-pbkdf2.1 + create mode 100644 util/grub-mkrelpath.1 + create mode 100644 util/grub-mkrescue.1 + create mode 100644 util/grub-mkstandalone.1 + create mode 100644 util/grub-ofpathname.8 + create mode 100644 util/grub-probe.8 + create mode 100644 util/grub-reboot.8 + create mode 100644 util/grub-render-label.1 + create mode 100644 util/grub-script-check.1 + create mode 100644 util/grub-set-default.8 + create mode 100644 util/grub-sparc64-setup.8 + +diff --git a/configure.ac b/configure.ac +index 8888c2ff29c..2632e2dad9b 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -70,6 +70,29 @@ grub_TRANSFORM([grub-set-default]) + grub_TRANSFORM([grub-sparc64-setup]) + grub_TRANSFORM([grub-render-label]) + grub_TRANSFORM([grub-file]) ++grub_TRANSFORM([grub-bios-setup.3]) ++grub_TRANSFORM([grub-editenv.1]) ++grub_TRANSFORM([grub-fstest.3]) ++grub_TRANSFORM([grub-glue-efi.3]) ++grub_TRANSFORM([grub-install.1]) ++grub_TRANSFORM([grub-kbdcomp.3]) ++grub_TRANSFORM([grub-menulst2cfg.1]) ++grub_TRANSFORM([grub-mkconfig.1]) ++grub_TRANSFORM([grub-mkfont.3]) ++grub_TRANSFORM([grub-mkimage.1]) ++grub_TRANSFORM([grub-mklayout.3]) ++grub_TRANSFORM([grub-mknetdir.3]) ++grub_TRANSFORM([grub-mkpasswd-pbkdf2.3]) ++grub_TRANSFORM([grub-mkrelpath.3]) ++grub_TRANSFORM([grub-mkrescue.1]) ++grub_TRANSFORM([grub-mkstandalone.3]) ++grub_TRANSFORM([grub-ofpathname.3]) ++grub_TRANSFORM([grub-probe.3]) ++grub_TRANSFORM([grub-reboot.3]) ++grub_TRANSFORM([grub-render-label.3]) ++grub_TRANSFORM([grub-script-check.3]) ++grub_TRANSFORM([grub-set-default.1]) ++grub_TRANSFORM([grub-sparc64-setup.3]) + + # Optimization flag. Allow user to override. + if test "x$TARGET_CFLAGS" = x; then +diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist +index 51f08c1f901..e914dfd897e 100644 +--- a/conf/Makefile.extra-dist ++++ b/conf/Makefile.extra-dist +@@ -10,7 +10,6 @@ EXTRA_DIST += unicode + EXTRA_DIST += util/import_gcry.py + EXTRA_DIST += util/import_unicode.py + +-EXTRA_DIST += docs/man + EXTRA_DIST += docs/autoiso.cfg + EXTRA_DIST += docs/grub.cfg + EXTRA_DIST += docs/osdetect.cfg +diff --git a/docs/Makefile.am b/docs/Makefile.am +index 93eb3962765..ab28f199694 100644 +--- a/docs/Makefile.am ++++ b/docs/Makefile.am +@@ -5,5 +5,3 @@ info_TEXINFOS = grub.texi grub-dev.texi + grub_TEXINFOS = fdl.texi + + EXTRA_DIST = font_char_metrics.png font_char_metrics.txt +- +- +diff --git a/docs/man/grub-bios-setup.h2m b/docs/man/grub-bios-setup.h2m +deleted file mode 100644 +index ac6ede36296..00000000000 +--- a/docs/man/grub-bios-setup.h2m ++++ /dev/null +@@ -1,6 +0,0 @@ +-[NAME] +-grub-bios-setup \- set up a device to boot using GRUB +-[SEE ALSO] +-.BR grub-install (8), +-.BR grub-mkimage (1), +-.BR grub-mkrescue (1) +diff --git a/docs/man/grub-editenv.h2m b/docs/man/grub-editenv.h2m +deleted file mode 100644 +index 3859d3d4c4f..00000000000 +--- a/docs/man/grub-editenv.h2m ++++ /dev/null +@@ -1,5 +0,0 @@ +-[NAME] +-grub-editenv \- edit GRUB environment block +-[SEE ALSO] +-.BR grub-reboot (8), +-.BR grub-set-default (8) +diff --git a/docs/man/grub-emu.h2m b/docs/man/grub-emu.h2m +deleted file mode 100644 +index ef1c000656a..00000000000 +--- a/docs/man/grub-emu.h2m ++++ /dev/null +@@ -1,6 +0,0 @@ +-[NAME] +-grub-emu \- GRUB emulator +-[SEE ALSO] +-If you are trying to install GRUB, then you should use +-.BR grub-install (8) +-rather than this program. +diff --git a/docs/man/grub-file.h2m b/docs/man/grub-file.h2m +deleted file mode 100644 +index e09bb4d3101..00000000000 +--- a/docs/man/grub-file.h2m ++++ /dev/null +@@ -1,2 +0,0 @@ +-[NAME] +-grub-file \- check file type +diff --git a/docs/man/grub-fstest.h2m b/docs/man/grub-fstest.h2m +deleted file mode 100644 +index 9676b159afd..00000000000 +--- a/docs/man/grub-fstest.h2m ++++ /dev/null +@@ -1,4 +0,0 @@ +-[NAME] +-grub-fstest \- debug tool for GRUB filesystem drivers +-[SEE ALSO] +-.BR grub-probe (8) +diff --git a/docs/man/grub-glue-efi.h2m b/docs/man/grub-glue-efi.h2m +deleted file mode 100644 +index c1c6ded49ff..00000000000 +--- a/docs/man/grub-glue-efi.h2m ++++ /dev/null +@@ -1,4 +0,0 @@ +-[NAME] +-grub-glue-efi \- generate a fat binary for EFI +-[DESCRIPTION] +-grub-glue-efi processes ia32 and amd64 EFI images and glues them according to Apple format. +diff --git a/docs/man/grub-install.h2m b/docs/man/grub-install.h2m +deleted file mode 100644 +index 8cbbc87a0f2..00000000000 +--- a/docs/man/grub-install.h2m ++++ /dev/null +@@ -1,6 +0,0 @@ +-[NAME] +-grub-install \- install GRUB to a device +-[SEE ALSO] +-.BR grub-mkconfig (8), +-.BR grub-mkimage (1), +-.BR grub-mkrescue (1) +diff --git a/docs/man/grub-kbdcomp.h2m b/docs/man/grub-kbdcomp.h2m +deleted file mode 100644 +index d81f9157e01..00000000000 +--- a/docs/man/grub-kbdcomp.h2m ++++ /dev/null +@@ -1,10 +0,0 @@ +-[NAME] +-grub-kbdcomp \- generate a GRUB keyboard layout file +-[DESCRIPTION] +-grub-kbdcomp processes a X keyboard layout description in +-.BR keymaps (5) +-format into a format that can be used by GRUB's +-.B keymap +-command. +-[SEE ALSO] +-.BR grub-mklayout (8) +diff --git a/docs/man/grub-macbless.h2m b/docs/man/grub-macbless.h2m +deleted file mode 100644 +index 0197c0087d7..00000000000 +--- a/docs/man/grub-macbless.h2m ++++ /dev/null +@@ -1,4 +0,0 @@ +-[NAME] +-grub-macbless \- bless a mac file/directory +-[SEE ALSO] +-.BR grub-install (1) +diff --git a/docs/man/grub-macho2img.h2m b/docs/man/grub-macho2img.h2m +deleted file mode 100644 +index d79aaeed8f9..00000000000 +--- a/docs/man/grub-macho2img.h2m ++++ /dev/null +@@ -1,4 +0,0 @@ +-[NAME] +-grub-macho2img \- convert Mach-O to raw image +-[SEE ALSO] +-.BR grub-mkimage (1) +diff --git a/docs/man/grub-menulst2cfg.h2m b/docs/man/grub-menulst2cfg.h2m +deleted file mode 100644 +index c2e0055ed7e..00000000000 +--- a/docs/man/grub-menulst2cfg.h2m ++++ /dev/null +@@ -1,4 +0,0 @@ +-[NAME] +-grub-menulst2cfg \- transform legacy menu.lst into grub.cfg +-[SEE ALSO] +-.BR grub-mkconfig (8) +diff --git a/docs/man/grub-mkconfig.h2m b/docs/man/grub-mkconfig.h2m +deleted file mode 100644 +index 9b42f813010..00000000000 +--- a/docs/man/grub-mkconfig.h2m ++++ /dev/null +@@ -1,4 +0,0 @@ +-[NAME] +-grub-mkconfig \- generate a GRUB configuration file +-[SEE ALSO] +-.BR grub-install (8) +diff --git a/docs/man/grub-mkfont.h2m b/docs/man/grub-mkfont.h2m +deleted file mode 100644 +index d46fe600eca..00000000000 +--- a/docs/man/grub-mkfont.h2m ++++ /dev/null +@@ -1,4 +0,0 @@ +-[NAME] +-grub-mkfont \- make GRUB font files +-[SEE ALSO] +-.BR grub-mkconfig (8) +diff --git a/docs/man/grub-mkimage.h2m b/docs/man/grub-mkimage.h2m +deleted file mode 100644 +index f0fbc2bb197..00000000000 +--- a/docs/man/grub-mkimage.h2m ++++ /dev/null +@@ -1,6 +0,0 @@ +-[NAME] +-grub-mkimage \- make a bootable image of GRUB +-[SEE ALSO] +-.BR grub-install (8), +-.BR grub-mkrescue (1), +-.BR grub-mknetdir (8) +diff --git a/docs/man/grub-mklayout.h2m b/docs/man/grub-mklayout.h2m +deleted file mode 100644 +index 1e43409c0ab..00000000000 +--- a/docs/man/grub-mklayout.h2m ++++ /dev/null +@@ -1,10 +0,0 @@ +-[NAME] +-grub-mklayout \- generate a GRUB keyboard layout file +-[DESCRIPTION] +-grub-mklayout processes a keyboard layout description in +-.BR keymaps (5) +-format into a format that can be used by GRUB's +-.B keymap +-command. +-[SEE ALSO] +-.BR grub-mkconfig (8) +diff --git a/docs/man/grub-mknetdir.h2m b/docs/man/grub-mknetdir.h2m +deleted file mode 100644 +index a2ef13ec111..00000000000 +--- a/docs/man/grub-mknetdir.h2m ++++ /dev/null +@@ -1,4 +0,0 @@ +-[NAME] +-grub-mknetdir \- prepare a GRUB netboot directory. +-[SEE ALSO] +-.BR grub-mkimage (1) +diff --git a/docs/man/grub-mkpasswd-pbkdf2.h2m b/docs/man/grub-mkpasswd-pbkdf2.h2m +deleted file mode 100644 +index 4d202f3da7e..00000000000 +--- a/docs/man/grub-mkpasswd-pbkdf2.h2m ++++ /dev/null +@@ -1,4 +0,0 @@ +-[NAME] +-grub-mkpasswd-pbkdf2 \- generate hashed password for GRUB +-[SEE ALSO] +-.BR grub-mkconfig (8) +diff --git a/docs/man/grub-mkrelpath.h2m b/docs/man/grub-mkrelpath.h2m +deleted file mode 100644 +index d01f3961e3f..00000000000 +--- a/docs/man/grub-mkrelpath.h2m ++++ /dev/null +@@ -1,4 +0,0 @@ +-[NAME] +-grub-mkrelpath \- make a system path relative to its root +-[SEE ALSO] +-.BR grub-probe (8) +diff --git a/docs/man/grub-mkrescue.h2m b/docs/man/grub-mkrescue.h2m +deleted file mode 100644 +index a427f02e3c6..00000000000 +--- a/docs/man/grub-mkrescue.h2m ++++ /dev/null +@@ -1,4 +0,0 @@ +-[NAME] +-grub-mkrescue \- make a GRUB rescue image +-[SEE ALSO] +-.BR grub-mkimage (1) +diff --git a/docs/man/grub-mkstandalone.h2m b/docs/man/grub-mkstandalone.h2m +deleted file mode 100644 +index c77313978ad..00000000000 +--- a/docs/man/grub-mkstandalone.h2m ++++ /dev/null +@@ -1,4 +0,0 @@ +-[NAME] +-grub-mkstandalone \- make a memdisk-based GRUB image +-[SEE ALSO] +-.BR grub-mkimage (1) +diff --git a/docs/man/grub-mount.h2m b/docs/man/grub-mount.h2m +deleted file mode 100644 +index 8d168982d72..00000000000 +--- a/docs/man/grub-mount.h2m ++++ /dev/null +@@ -1,2 +0,0 @@ +-[NAME] +-grub-mount \- export GRUB filesystem with FUSE +diff --git a/docs/man/grub-ofpathname.h2m b/docs/man/grub-ofpathname.h2m +deleted file mode 100644 +index 74b43eea039..00000000000 +--- a/docs/man/grub-ofpathname.h2m ++++ /dev/null +@@ -1,4 +0,0 @@ +-[NAME] +-grub-ofpathname \- find OpenBOOT path for a device +-[SEE ALSO] +-.BR grub-probe (8) +diff --git a/docs/man/grub-pe2elf.h2m b/docs/man/grub-pe2elf.h2m +deleted file mode 100644 +index 7ca29bd703c..00000000000 +--- a/docs/man/grub-pe2elf.h2m ++++ /dev/null +@@ -1,4 +0,0 @@ +-[NAME] +-grub-pe2elf \- convert PE image to ELF +-[SEE ALSO] +-.BR grub-mkimage (1) +diff --git a/docs/man/grub-probe.h2m b/docs/man/grub-probe.h2m +deleted file mode 100644 +index 6e1ffdcf937..00000000000 +--- a/docs/man/grub-probe.h2m ++++ /dev/null +@@ -1,4 +0,0 @@ +-[NAME] +-grub-probe \- probe device information for GRUB +-[SEE ALSO] +-.BR grub-fstest (1) +diff --git a/docs/man/grub-reboot.h2m b/docs/man/grub-reboot.h2m +deleted file mode 100644 +index e4acace65ce..00000000000 +--- a/docs/man/grub-reboot.h2m ++++ /dev/null +@@ -1,5 +0,0 @@ +-[NAME] +-grub-reboot \- set the default boot entry for GRUB, for the next boot only +-[SEE ALSO] +-.BR grub-set-default (8), +-.BR grub-editenv (1) +diff --git a/docs/man/grub-render-label.h2m b/docs/man/grub-render-label.h2m +deleted file mode 100644 +index 50ae5247c05..00000000000 +--- a/docs/man/grub-render-label.h2m ++++ /dev/null +@@ -1,3 +0,0 @@ +-[NAME] +-grub-render-label \- generate a .disk_label for Apple Macs. +- +diff --git a/docs/man/grub-script-check.h2m b/docs/man/grub-script-check.h2m +deleted file mode 100644 +index 3653682671a..00000000000 +--- a/docs/man/grub-script-check.h2m ++++ /dev/null +@@ -1,4 +0,0 @@ +-[NAME] +-grub-script-check \- check grub.cfg for syntax errors +-[SEE ALSO] +-.BR grub-mkconfig (8) +diff --git a/docs/man/grub-set-default.h2m b/docs/man/grub-set-default.h2m +deleted file mode 100644 +index 7945001c154..00000000000 +--- a/docs/man/grub-set-default.h2m ++++ /dev/null +@@ -1,5 +0,0 @@ +-[NAME] +-grub-set-default \- set the saved default boot entry for GRUB +-[SEE ALSO] +-.BR grub-reboot (8), +-.BR grub-editenv (1) +diff --git a/docs/man/grub-sparc64-setup.h2m b/docs/man/grub-sparc64-setup.h2m +deleted file mode 100644 +index 18f803a50db..00000000000 +--- a/docs/man/grub-sparc64-setup.h2m ++++ /dev/null +@@ -1,6 +0,0 @@ +-[NAME] +-grub-sparc64-setup \- set up a device to boot using GRUB +-[SEE ALSO] +-.BR grub-install (8), +-.BR grub-mkimage (1), +-.BR grub-mkrescue (1) +diff --git a/docs/man/grub-syslinux2cfg.h2m b/docs/man/grub-syslinux2cfg.h2m +deleted file mode 100644 +index ad25c8ab753..00000000000 +--- a/docs/man/grub-syslinux2cfg.h2m ++++ /dev/null +@@ -1,4 +0,0 @@ +-[NAME] +-grub-syslinux2cfg \- transform syslinux config into grub.cfg +-[SEE ALSO] +-.BR grub-menulst2cfg (8) +diff --git a/gentpl.py b/gentpl.py +index bdcae1a1c1b..889cc91d39c 100644 +--- a/gentpl.py ++++ b/gentpl.py +@@ -792,10 +792,7 @@ def manpage(defn, adddeps): + + output("if COND_MAN_PAGES\n") + gvar_add("man_MANS", name + "." + mansection) +- rule(name + "." + mansection, name + " " + adddeps, """ +-chmod a+x """ + name + """ +-PATH=$(builddir):$$PATH pkgdatadir=$(builddir) $(HELP2MAN) --section=""" + mansection + """ -i $(top_srcdir)/docs/man/""" + name + """.h2m -o $@ """ + name + """ +-""") ++ rule(name + "." + mansection, name + " " + adddeps, "cat $(top_srcdir)/util/" + name + "." + mansection + " | $(top_builddir)/config.status --file=$@:-") + gvar_add("CLEANFILES", name + "." + mansection) + output("endif\n") + +diff --git a/util/grub-bios-setup.8 b/util/grub-bios-setup.8 +new file mode 100644 +index 00000000000..56f582b3d75 +--- /dev/null ++++ b/util/grub-bios-setup.8 +@@ -0,0 +1,54 @@ ++.TH GRUB-BIOS-SETUP 3 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-bios-setup\fR \(em Set up images to boot from a device. ++ ++.SH SYNOPSIS ++\fBgrub-bios-setup\fR [-a | --allow-floppy] [-b | --boot-image=\fIFILE\fR] ++.RS 17 ++[-c | --core-image=\fIFILE\fR] [-d | --directory=\fIDIR\fR] ++.RE ++.RS 17 ++[-f | --force] [-m | --device-map=\fIFILE\fR] ++.RE ++.RS 17 ++[-s | --skip-fs-probe] [-v | --verbose] \fIDEVICE\fR ++ ++.SH DESCRIPTION ++You should not normally run this program directly. Use grub-install instead. ++ ++.SH OPTIONS ++.TP ++\fB--allow-floppy\fR ++Make the device also bootable as a floppy. This option is the default for ++/dev/fdX devices. Some BIOSes will not boot images created with this option. ++ ++.TP ++\fB--boot-image\fR=\fIFILE\fR ++Use FILE as the boot image. The default value is \fBboot.img\fR. ++ ++.TP ++\fB--core-image\fR=\fIFILE\fR ++Use FILE as ther core image. The default value is \fBcore.img\fR. ++ ++.TP ++\fB--directory\fR=\fIDIR\fR ++Use GRUB files in the directory DIR. The default value is \fB/boot/grub\fR. ++ ++.TP ++\fB--force\fR ++Install even if problems are detected. ++ ++.TP ++\fB--device-map\fR=\fIFILE\fR ++Use FILE as the device map. The default value is /boot/grub/device.map . ++ ++.TP ++\fB--skip-fs-probe\fR ++Do not probe DEVICE for filesystems. ++ ++.TP ++\fB--verbose\fR ++Print verbose messages. ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-editenv.1 b/util/grub-editenv.1 +new file mode 100644 +index 00000000000..8dad33f8db6 +--- /dev/null ++++ b/util/grub-editenv.1 +@@ -0,0 +1,46 @@ ++.TH GRUB-EDITENV 1 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-editenv\fR \(em Manage the GRUB environment block. ++ ++.SH SYNOPSIS ++\fBgrub-editenv\fR [-v | --verbose] [\fIFILE\fR] ++.RS 14 ++ ++ ++.SH DESCRIPTION ++\fBgrub-editenv\fR is a command line tool to manage GRUB's stored environment. ++ ++.SH OPTIONS ++.TP ++\fB--verbose\fR ++Print verbose messages. ++ ++.TP ++\fBFILE\fR ++.RS 7 ++File name to use for grub environment. Default is /boot/grub/grubenv . ++.RE ++ ++.SH COMMANDS ++.TP ++\fBcreate\fR ++.RS 7 ++Create a blank environment block file. ++.RE ++ ++.TP ++\fBlist\fR ++.RS 7 ++List the current variables. ++.RE ++ ++.TP ++\fBset\fR [\fINAME\fR=\fIVALUE\fR ...] ++Set variables. ++ ++.TP ++\fBunset [\fINAME\fR ...] ++Delete variables. ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-file.1 b/util/grub-file.1 +new file mode 100644 +index 00000000000..b29cb327889 +--- /dev/null ++++ b/util/grub-file.1 +@@ -0,0 +1,165 @@ ++.TH GRUB-FILE 1 "Web Feb 26 2014" ++.SH NAME ++\fBgrub-file\fR \(em Check if FILE is of specified type. ++ ++.SH SYNOPSIS ++\fBgrub-file\fR (--is-i386-xen-pae-domu | --is-x86_64-xen-domu | ++.RS 11 ++--is-x86-xen-dom0 | --is-x86-multiboot | ++.RE ++.RS 11 ++--is-x86-multiboot2 | --is-arm-linux | --is-arm64-linux | ++.RE ++.RS 11 ++--is-ia64-linux | --is-mips-linux | --is-mipsel-linux | ++.RE ++.RS 11 ++--is-sparc64-linux | --is-powerpc-linux | --is-x86-linux | ++.RE ++.RS 11 ++--is-x86-linux32 | --is-x86-kfreebsd | --is-i386-kfreebsd | ++.RE ++.RS 11 ++--is-x86_64-kfreebsd | --is-x86-knetbsd | ++.RE ++.RS 11 ++--is-i386-knetbsd | --is-x86_64-knetbsd | --is-i386-efi | ++.RE ++.RS 11 ++--is-x86_64-efi | --is-ia64-efi | --is-arm64-efi | ++.RE ++.RS 11 ++--is-arm-efi | --is-hibernated-hiberfil | --is-x86_64-xnu | ++.RE ++.RS 11 ++--is-i386-xnu | --is-xnu-hibr | --is-x86-bios-bootsector) ++.RE ++.RS 11 ++\fIFILE\fR ++ ++.SH DESCRIPTION ++\fBgrub-file\fR is used to check if \fIFILE\fR is of a specified type. ++ ++.SH OPTIONS ++.TP ++--is-i386-xen-pae-domu ++Check if FILE can be booted as i386 PAE Xen unprivileged guest kernel ++ ++.TP ++--is-x86_64-xen-domu ++Check if FILE can be booted as x86_64 Xen unprivileged guest kernel ++ ++.TP ++--is-x86-xen-dom0 ++Check if FILE can be used as Xen x86 privileged guest kernel ++ ++.TP ++--is-x86-multiboot ++Check if FILE can be used as x86 multiboot kernel ++ ++.TP ++--is-x86-multiboot2 ++Check if FILE can be used as x86 multiboot2 kernel ++ ++.TP ++--is-arm-linux ++Check if FILE is ARM Linux ++ ++.TP ++--is-arm64-linux ++Check if FILE is ARM64 Linux ++ ++.TP ++--is-ia64-linux ++Check if FILE is IA64 Linux ++ ++.TP ++--is-mips-linux ++Check if FILE is MIPS Linux ++ ++.TP ++--is-mipsel-linux ++Check if FILE is MIPSEL Linux ++ ++.TP ++--is-sparc64-linux ++Check if FILE is SPARC64 Linux ++ ++.TP ++--is-powerpc-linux ++Check if FILE is POWERPC Linux ++ ++.TP ++--is-x86-linux ++Check if FILE is x86 Linux ++ ++.TP ++--is-x86-linux32 ++Check if FILE is x86 Linux supporting 32-bit protocol ++ ++.TP ++--is-x86-kfreebsd ++Check if FILE is x86 kFreeBSD ++ ++.TP ++--is-i386-kfreebsd ++Check if FILE is i386 kFreeBSD ++ ++.TP ++--is-x86_64-kfreebsd ++Check if FILE is x86_64 kFreeBSD ++ ++.TP ++--is-x86-knetbsd ++Check if FILE is x86 kNetBSD ++ ++.TP ++--is-i386-knetbsd ++Check if FILE is i386 kNetBSD ++ ++.TP ++--is-x86_64-knetbsd ++Check if FILE is x86_64 kNetBSD ++ ++.TP ++--is-i386-efi ++Check if FILE is i386 EFI file ++ ++.TP ++--is-x86_64-efi ++Check if FILE is x86_64 EFI file ++ ++.TP ++--is-ia64-efi ++Check if FILE is IA64 EFI file ++ ++.TP ++--is-arm64-efi ++Check if FILE is ARM64 EFI file ++ ++.TP ++--is-arm-efi ++Check if FILE is ARM EFI file ++ ++.TP ++--is-hibernated-hiberfil ++Check if FILE is hiberfil.sys in hibernated state ++ ++.TP ++--is-x86_64-xnu ++Check if FILE is x86_64 XNU (Mac OS X kernel) ++ ++.TP ++--is-i386-xnu ++Check if FILE is i386 XNU (Mac OS X kernel) ++ ++.TP ++--is-xnu-hibr ++Check if FILE is XNU (Mac OS X kernel) hibernated image ++ ++.TP ++--is-x86-bios-bootsector ++Check if FILE is BIOS bootsector ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-fstest.1 b/util/grub-fstest.1 +new file mode 100644 +index 00000000000..792fa78634c +--- /dev/null ++++ b/util/grub-fstest.1 +@@ -0,0 +1,99 @@ ++.TH GRUB-FSTEST 3 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-fstest\fR — Debug tool for GRUB's filesystem driver. ++ ++.SH SYNOPSIS ++\fBgrub-fstest\fR [-c | --diskcount=\fINUM\fR] [-C | --crypto] ++.RS 13 ++[-d | --debug=\fISTRING\fR] [-K | --zfs-key=\fIFILE\fR|\fIprompt\fR] ++.RE ++.RS 13 ++[-n | --length=\fINUM\fR] [-r | --root=\fIDEVICE_NAME\fR] ++.RE ++.RS 13 ++[-s | --skip=\fINUM\fR] [-u | --uncompress] [-v | --verbose] ++.RE ++.RS 13 ++\fIIMAGE_PATH\fR ++ ++.SH DESCRIPTION ++\fBgrub-fstest\fR is a tool for testing GRUB's filesystem drivers. You should not normally need to run this program. ++ ++.SH OPTIONS ++.TP ++\fB--diskcount\fR=\fINUM\fR ++Specify the number of input files. ++ ++.TP ++\fB--crypto\fR ++Mount cryptographic devices. ++ ++.TP ++\fB--debug\fR=\fISTRING\fR ++Set debug environment variable. ++ ++.TP ++\fB--zfs-key\fR=\fIFILE\fR|\fIprompt\fR ++Load ZFS cryptographic key. ++ ++.TP ++\fB--length\fR=\fINUM\fR ++Handle NUM bytes in output file. ++ ++.TP ++\fB--root\fR=\fIDEVICE_NAME\fR ++Set root device. ++ ++.TP ++\fB--skip\fR=\fINUM\fR ++Skip NUM bytes from output file. ++ ++.TP ++\fB--uncompress\fR ++Uncompress data. ++ ++.TP ++\fB--verbose\fR ++Print verbose messages. ++ ++.SH COMMANDS ++.TP ++\fBblocklist\fR \fIFILE\fR ++Display block list of \fIFILE\fR. ++ ++.TP ++\fBcat\fR \fIFILE\fR ++Display \fIFILE\fR on standard output. ++ ++.TP ++\fBcmp\fR \fIFILE\fR \fILOCAL\fR ++Compare \fIFILE\fR with local file \fILOCAL\fR. ++ ++.TP ++\fBcp\fR \fIFILE\fR \fILOCAL\fR ++Copy \fIFILE\fR to local file \fILOCAL\fR. ++ ++.TP ++\fBcrc\fR \fIFILE\fR ++Display the CRC-32 checksum of \fIFILE\fR. ++ ++.TP ++\fBhex\fR \fIFILE\fR ++Display contents of \fIFILE\fR in hexidecimal. ++ ++.TP ++\fBls\fR \fIPATH\fR ++List files at \fIPATH\fR. ++ ++.TP ++\fBxnu_uuid\fR \fIDEVICE\fR ++Display the XNU UUID of \fIDEVICE\fR. ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-glue-efi.1 b/util/grub-glue-efi.1 +new file mode 100644 +index 00000000000..72bd555d577 +--- /dev/null ++++ b/util/grub-glue-efi.1 +@@ -0,0 +1,31 @@ ++.TH GRUB-GLUE-EFI 3 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-glue-efi\fR \(em Create an Apple fat EFI binary. ++ ++.SH SYNOPSIS ++\fBgrub-glue-efi\fR <-3 | --input32=\fIFILE\fR> <-6 | --input64=\fIFILE\fR> ++.RS 15 ++<-o | --output=\fIFILE\fR> [-v | --verbose] ++ ++.SH DESCRIPTION ++\fBgrub-glue-efi\fR creates an Apple fat EFI binary from two EFI binaries. ++ ++.SH OPTIONS ++.TP ++\fB--input32\fR=\fIFILE\fR ++Read 32-bit binary from \fIFILE\fR. ++ ++.TP ++\fB--input64\fR=\fIFILE\fR ++Read 64-bit binary from \fIFILE\fR. ++ ++.TP ++\fB--output\fR=\fIFILE\fR ++Write resulting fat binary to \fIFILE\fR. ++ ++.TP ++\fB--verbose\fR ++Print verbose messages. ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-install.8 b/util/grub-install.8 +new file mode 100644 +index 00000000000..76272a39d2e +--- /dev/null ++++ b/util/grub-install.8 +@@ -0,0 +1,129 @@ ++.TH GRUB-INSTALL 1 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-install\fR \(em Install GRUB on a device. ++ ++.SH SYNOPSIS ++\fBgrub-install\fR [--modules=\fIMODULES\fR] [--install-modules=\fIMODULES\fR] ++.RS 14 ++[--themes=\fITHEMES\fR] [--fonts=\fIFONTS\fR] [--locales=\fILOCALES\fR] ++.RE ++.RS 14 ++[--compress[=\fIno\fR,\fIxz\fR,\fIgz\fR,\fIlzo\fR]] [-d | --directory=\fIDIR\fR] ++.RE ++.RS 14 ++[--grub-mkimage=\fIFILE\fR] [--boot-directory=\fIDIR\fR] ++.RE ++.RS 14 ++[--target=\fITARGET\fR] [--grub-setup=\fIFILE\fR] ++.RE ++.RS 14 ++[--grub-mkrelpath=\fIFILE\fR] [--grub-probe=\fIFILE\fR] ++.RE ++.RS 14 ++[--allow-floppy] [--recheck] [--force] [--force-file-id] ++.RE ++.RS 14 ++[--disk-module=\fIMODULE\fR] [--no-nvram] [--removable] ++.RE ++.RS 14 ++[--bootloader-id=\fIID\fR] [--efi-directory=\fIDIR\fR] \fIINSTALL_DEVICE\fR ++ ++.SH DESCRIPTION ++\fBgrub-install\fR installs GRUB onto a device. This includes copying GRUB images into the target directory (generally \fI/boot/grub\fR), and on some platforms may also include installing GRUB onto a boot sector. ++ ++.SH OPTIONS ++.TP ++\fB--modules\fR=\fIMODULES\fR\! ++Pre-load modules specified by \fIMODULES\fR. ++ ++.TP ++\fB--install-modules\fR=\fIMODULES\fR ++Install only \fIMODULES\fR and their dependencies. The default is to install all available modules. ++ ++.TP ++\fB--themes\fR=\fITHEMES\fR ++Install \fITHEMES\fR. The default is to install the \fIstarfield\fR theme, if available. ++ ++.TP ++\fB--fonts\fR=\fIFONTS\fR ++Install \fIFONTS\fR. The default is to install the \fIunicode\fR font. ++ ++.TP ++\fB--locales\fR=\fILOCALES\fR ++Install only locales listed in \fILOCALES\fR. The default is to install all available locales. ++ ++.TP ++\fB--compress\fR=\fIno\fR,\fIxz\fR,\fIgz\fR,\fIlzo\fR ++Compress GRUB files using the specified compression algorithm. ++ ++.TP ++\fB--directory\fR=\fIDIR\fR ++Use images and modules in \fIDIR\fR. ++ ++.TP ++\fB--grub-mkimage\fR=\fIFILE\fR ++Use \fIFILE\fR as \fBgrub-mkimage\fR. The default is \fI/usr/bin/grub-mkimage\fR. ++ ++.TP ++\fB--boot-directory\fR=\fIDIR\fR ++Use \fIDIR\fR as the boot directory. The default is \fI/boot\fR. GRUB will put its files in a subdirectory of this directory named \fIgrub\fR. ++ ++.TP ++\fB--target\fR=\fITARGET\fR ++Install GRUB for \fITARGET\fR platform. The default is the platform \fBgrub-install\fR is running on. ++ ++.TP ++\fB--grub-setup\fR=\fIFILE\fR ++Use \fIFILE\fR as \fBgrub-setup\fR. The default is \fI/usr/bin/grub-setup\fR. ++ ++.TP ++\fB--grub-mkrelpath\fR=\fIFILE\fR ++Use \fIFILE\fR as \fBgrub-mkrelpath\fR. The default is \fI/usr/bin/grub-mkrelpath\fR. ++ ++.TP ++\fB--grub-probe\fR=\fIFILE\fR ++Use \fIFILE\fR as \fBgrub-probe\fR. The default is \fI/usr/bin/grub-mkrelpath\fR. ++ ++.TP ++\fB--allow-floppy ++Make the device also bootable as a floppy. This option is the default for /dev/fdX devices. Some BIOSes will not boot images created with this option. ++ ++.TP ++\fB--recheck ++Delete any existing device map and create a new one if necessary. ++ ++.TP ++\fB--force ++Install even if problems are detected. ++ ++.TP ++\fB--force-file-id ++Use identifier file even if UUID is available. ++ ++.TP ++\fB--disk-module\fR=\fIMODULE\fR ++Use \fIMODULE\fR for disk access. This allows you to manually specify either \fIbiosdisk\fR or \fInative\fR disk access. This option is only available on the BIOS target platform. ++ ++.TP ++\fB--no-nvram ++Do not update the \fIboot-device\fR NVRAM variable. This option is only available on IEEE1275 target platforms. ++ ++.TP ++\fB--removable ++Treat the target device as if it is removeable. This option is only available on the EFI target platform. ++ ++.TP ++\fB--bootloader-id\fR=\fIID\fR ++Use \fIID\fR as the bootloader ID. This opption is only available on the EFI target platform. ++ ++.TP ++\fB--efi-directory\fR=\fIDIR\fR ++Use \fIDIR\fR as the EFI System Partition root. This opption is only available on the EFI ta ++rget platform. ++ ++.TP ++\fIINSTALL_DEVICE\fR ++Install GRUB to the block device \fIINSTALL_DEVICE\fR. ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-kbdcomp.1 b/util/grub-kbdcomp.1 +new file mode 100644 +index 00000000000..0bb969a5b43 +--- /dev/null ++++ b/util/grub-kbdcomp.1 +@@ -0,0 +1,19 @@ ++.TH GRUB-KBDCOMP 3 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-kbdcomp\fR \(em Generate a GRUB keyboard layout file. ++ ++.SH SYNOPSIS ++\fBgrub-kbdcomp\fR <-o | --output=\fIFILE\fR> \fICKBMAP_ARGUMENTS\fR ++ ++.SH DESCRIPTION ++\fBgrub-kbdcomp\fR processes an X keyboard layout description in ++\fBkeymaps\fR(5) format into a format that can be used by GRUB's \fBkeymap\fR ++command. ++ ++.SH OPTIONS ++.TP ++\fB--output\fR=\fIFILE\fR ++Write output to \fIFILE\fR. ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-macbless.1 b/util/grub-macbless.1 +new file mode 100644 +index 00000000000..41a96186f70 +--- /dev/null ++++ b/util/grub-macbless.1 +@@ -0,0 +1,22 @@ ++.TH GRUB-MACBLESS 1 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-macbless\fR \(em Mac-style bless on HFS or HFS+ ++ ++.SH SYNOPSIS ++\fBgrub-macbless\fR [-v | --verbose] [-p | --ppc] \fIFILE\fR | [-x | --x86] \fIFILE\fR ++ ++.SH OPTIONS ++.TP ++--x86 ++Bless for x86 based Macs. ++ ++.TP ++--ppc ++Bless for PPC based Macs. ++ ++.TP ++--verbose ++Print verbose messages. ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-menulst2cfg.1 b/util/grub-menulst2cfg.1 +new file mode 100644 +index 00000000000..91e2ef87113 +--- /dev/null ++++ b/util/grub-menulst2cfg.1 +@@ -0,0 +1,12 @@ ++.TH GRUB-MENULST2CFG 1 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-menulst2cfg\fR \(em Convert a configuration file from GRUB 0.xx to GRUB 2.xx format. ++ ++.SH SYNOPSIS ++\fBgrub-menulst2cfg\fR [\fIINFILE\fR [\fIOUTFILE\fR]] ++ ++.SH DESCRIPTION ++\fBgrub-menulst2cfg\fR converts a configuration file from GRUB 0.xx to the current format. ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-mkconfig.8 b/util/grub-mkconfig.8 +new file mode 100644 +index 00000000000..a2d1f577b9b +--- /dev/null ++++ b/util/grub-mkconfig.8 +@@ -0,0 +1,17 @@ ++.TH GRUB-MKCONFIG 1 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-mkconfig\fR \(em Generate a GRUB configuration file. ++ ++.SH SYNOPSIS ++\fBgrub-mkconfig\fR [-o | --output=\fIFILE\fR] ++ ++.SH DESCRIPTION ++\fBgrub-mkconfig\fR generates a configuration file for GRUB. ++ ++.SH OPTIONS ++.TP ++\fB--output\fR=\fIFILE\fR ++Write generated output to \fIFILE\fR. ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-mkfont.1 b/util/grub-mkfont.1 +new file mode 100644 +index 00000000000..3494857987d +--- /dev/null ++++ b/util/grub-mkfont.1 +@@ -0,0 +1,87 @@ ++.TH GRUB-MKFONT 3 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-mkfont\fR \(em Convert common font file formats into the PF2 format. ++ ++.SH SYNOPSIS ++\fBgrub-mkfont\fR [--ascii-bitmaps] [-a | --force-autohint] ++.RS 13 ++[-b | --bold] [-c | --asce=\fINUM\fR] [-d | --desc=\fINUM\fR] ++.RE ++.RS 13 ++[-i | --index=\fINUM\fR] [-n | --name=\fINAME\fR] [--no-bitmap] ++.RE ++.RS 13 ++[--no-hinting] <-o | --output=\fIFILE\fR> ++.RE ++.RS 13 ++[-r | --range=\fIFROM-TO\fR[\fI,FROM-TO\fR]] [-s | --size=\fISIZE\fR] ++.RE ++.RS 13 ++[-v | --verbose] [--width-spec] \fIFONT_FILES\fR ++ ++.SH DESCRIPTION ++\fBgrub-mkfont\fR converts font files from common formats into the PF2 format used by GRUB. ++ ++.SH OPTIONS ++.TP ++--ascii-bitmaps ++Save only bitmaps for ASCII characters. ++ ++.TP ++--force-autohint ++Force generation of automatic hinting. ++ ++.TP ++--bold ++Convert font to bold. ++ ++.TP ++--asce=\fINUM\fR ++Set font ascent to \fINUM\fR. ++ ++.TP ++--desc=\fINUM\fR ++Set font descent to \fINUM\fR. ++ ++.TP ++--index=\fINUM\fR ++Select face index \fINUM\fR. ++ ++.TP ++--name=\fINAME\fR ++Set font family to \fINAME\fR. ++ ++.TP ++--no-bitmap ++Ignore bitmap strikes when loading. ++ ++.TP ++--no-hinting ++Disable hinting. ++ ++.TP ++--output=\fIFILE\fR ++Save ouptut to \fIFILE\fR. This argument is required. ++ ++.TP ++--range=\fIFROM-TO\fR\fI,FROM-TO\fR ++Set the font ranges to each pair of \fIFROM\fR,\fITO\fR. ++ ++.TP ++--size=\fISIZE\fR ++Set font size to \fISIZE\fR. ++ ++.TP ++--verbose ++Print verbose messages. ++ ++.TP ++--width-spec ++Create a width summary file. ++ ++.TP ++\fIFONT_FILES\fR ++The input files to be converted. ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-mkimage.1 b/util/grub-mkimage.1 +new file mode 100644 +index 00000000000..4dea4f54597 +--- /dev/null ++++ b/util/grub-mkimage.1 +@@ -0,0 +1,95 @@ ++.TH GRUB-MKIMAGE 1 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-mkimage\fR \(em Make a bootable GRUB image. ++ ++.SH SYNOPSIS ++\fBgrub-mkimage\fR [-c | --config=\fRFILE\fI] [-C | --compression=(\fIxz\fR,\fInone\fR,\fIauto\fR)] ++.RS 14 ++[-d | --directory=\fRDIR\fR] [-k | --pubkey=\fIFILE\fR] ++.RE ++.RS 14 ++[-m | --memdisk=\fIFILE\fR] [-n | --note] [-o | --output=\fIFILE\fR] ++.RE ++.RS 14 ++[-O | --format=\fIFORMAT\fR] [-p | --prefix=\fIDIR\fR] ++.RE ++.RS 14 ++[-v | --verbose] \fIMODULES\fR ++ ++.SH DESCRIPTION ++\fBgrub-mkimage\fI builds a bootable image of GRUB. ++ ++.SH OPTIONS ++.TP ++--config=\fIFILE\fR ++Embed \fIFILE\fR as the image's initial configuration file. ++ ++.TP ++--compression=(\fIxz\fR,\fInone\fR,\fIauto\fR) ++Use one of \fIxz\fR, \fInone\fR, or \fIauto\fR as the compression method for the core image. ++ ++.TP ++--directory=\fIDIR\fR ++Use images and modules from \fIDIR\fR. The default value is \fB/usr/lib/grub/\fR. ++ ++.TP ++--pubkey=\fIFILE\fR ++Embed the public key \fIFILE\fR for signature checking. ++ ++.TP ++--memdisk=\fIFILE\fR ++Embed the memdisk image \fIFILE\fR. If no \fB-p\fR option is also specified, this implies \fI-p (memdisk)/boot/grub\fR. ++ ++.TP ++--note ++Add a CHRP \fINOTE\fR section. This option is only valid on IEEE1275 platforms. ++ ++.TP ++--output=\fIFILE\fR ++Write the generated file to \fIFILE\fR. The default is to write to standard output. ++ ++.TP ++--format=\fIFORMAT\fR ++Generate an image in the specified \fIFORMAT\fR. Valid values are: ++.RS ++.RS 4 ++.P ++i386-coreboot, ++i386-multiboot, ++i386-pc, ++i386-pc-pxe, ++i386-efi, ++i386-ieee1275, ++i386-qemu, ++x86_64-efi, ++mipsel-yeeloong-flash, ++mipsel-fuloong2f-flash, ++mipself-loongson-elf, ++powerpc-ieee1275, ++sparc64-ieee1275-raw, ++sparc64-ieee1275-cdcore, ++sparc64-ieee1275-aout, ++ia64-efi, ++mips-arc, ++mipsel-arc, ++mipsel-qemu_mips-elf, ++mips-qemu_mips-flash, ++mipsel-qemu_mips-flash, ++mips-qemu_mips-elf ++.RE ++.RE ++ ++.TP ++--prefix=\fIDIR\fR ++Set prefix directory. The default value is \fI/boot/grub\fR. ++ ++.TP ++--verbose ++Print verbose messages. ++ ++.TP ++\fIMODULES\fR ++Include \fIMODULES\fR. ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-mklayout.1 b/util/grub-mklayout.1 +new file mode 100644 +index 00000000000..d1bbc2ec515 +--- /dev/null ++++ b/util/grub-mklayout.1 +@@ -0,0 +1,27 @@ ++.TH GRUB-MKLAYOUT 3 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-mklayout\fR \(em Generate a GRUB keyboard layout file. ++ ++.SH SYNOPSIS ++\fBgrub-mklayout\fR [-i | --input=\fIFILE\fR] [-o | --output=\fIFILE\fR] ++.RS 15 ++[-v | --verbose] ++ ++.SH DESCRIPTION ++\fBgrub-mklayout\fR generates a GRUB keyboard layout description which corresponds with the Linux console layout description given as input. ++ ++.SH OPTIONS ++.TP ++--input=\fIFILE\fR ++Use \fIFILE\fR as the input. The default value is the standard input device. ++ ++.TP ++--output=\fIFILE\fR ++Use \fIFILE\fR as the output. The default value is the standard output device. ++ ++.TP ++--verbose ++Print verbose messages. ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-mknetdir.1 b/util/grub-mknetdir.1 +new file mode 100644 +index 00000000000..69c22628f82 +--- /dev/null ++++ b/util/grub-mknetdir.1 +@@ -0,0 +1,12 @@ ++.TH GRUB-MKNETDIR 3 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-mknetdir\fR \(em Prepare a GRUB netboot directory. ++ ++.SH SYNOPSIS ++\fBgrub-mknetdir\fR ++ ++.SH DESCRIPTION ++\fBgrub-mknetdir\fR prepares a directory for GRUB to be netbooted from. ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-mkpasswd-pbkdf2.1 b/util/grub-mkpasswd-pbkdf2.1 +new file mode 100644 +index 00000000000..73c437c15d8 +--- /dev/null ++++ b/util/grub-mkpasswd-pbkdf2.1 +@@ -0,0 +1,27 @@ ++.TH GRUB-MKPASSWD-PBKDF2 3 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-mkpasswd-pbkdf2\fR \(em Generate a PBKDF2 password hash. ++ ++.SH SYNOPSIS ++\fBgrub-mkpasswd-pbkdf2\fR [-c | --iteration-count=\fINUM\fR] [-l | --buflen=\fINUM\fR] ++.RS 22 ++[-s | --salt=\fINUM\fR] ++ ++.SH DESCRIPTION ++\fBgrub-mkpasswd-pbkdf2\fR generates a PBKDF2 password string suitable for use in a GRUB configuration file. ++ ++.SH OPTIONS ++.TP ++--iteration-count=\fINUM\fR ++Number of PBKDF2 iterations. ++ ++.TP ++--buflen=\fINUM\fR ++Length of generated hash. ++ ++.TP ++--salt=\fINUM\fR ++Length of salt to use. ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-mkrelpath.1 b/util/grub-mkrelpath.1 +new file mode 100644 +index 00000000000..85f1113621d +--- /dev/null ++++ b/util/grub-mkrelpath.1 +@@ -0,0 +1,12 @@ ++.TH GRUB-MKRELPATH 3 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-mkrelpath\fR \(em Generate a relative GRUB path given an OS path. ++ ++.SH SYNOPSIS ++\fBgrub-mkrelpath\fR \fIFILE\fR ++ ++.SH DESCRIPTION ++\fBgrub-mkrelpath\fR takes an OS filesystem path for \fIFILE\fR and returns a relative path suitable for use in a GRUB configuration file. ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-mkrescue.1 b/util/grub-mkrescue.1 +new file mode 100644 +index 00000000000..4ed9fc723fd +--- /dev/null ++++ b/util/grub-mkrescue.1 +@@ -0,0 +1,123 @@ ++.TH GRUB-MKRESCUE 3 "Wed Feb 26 2014" ++.SH NAME ++grub-mkrescue \(em Generate a GRUB rescue image using GNU Xorriso. ++ ++.SH SYNOPSIS ++\fBgrub-mkrescue\fR [-o | --output=\fIFILE\fR] [--modules=\fIMODULES\fR] ++.RS 15 ++[--install-modules=\fIMODULES\fR] [--themes=\fITHEMES\fR] ++.RE ++.RS 15 ++[--fonts=\fIFONTS\fR] [--locales=\fILOCALES\fR] ++.RE ++.RS 15 ++[--compress[=\fIno\fR,\fIxz\fR,\fIgz\fR,\fIlzo\fR]] [-d | --directory=\fIDIR\fR] ++.RE ++.RS 15 ++[--grub-mkimage=\fIFILE\fR] [--rom-directory=\fIDIR\fR] ++.RE ++.RS 15 ++[--xorriso=\fIFILE\fR] [--grub-glue-efi=\fIFILE\fR] ++.RE ++.RS 15 ++[--grub-render-label=\fIFILE\fR] [--label-font=\fIFILE\fR] ++.RE ++.RS 15 ++[--label-color=\fICOLOR\fR] [--label-bgcolor=\fIFILE\fR] ++.RE ++.RS 15 ++[--product-name=\fISTRING\fR] [--product-version=\fISTRING\fR] ++.RE ++.RS 15 ++[--sparc-boot] [--arcs-boot] ++ ++.SH DESCRIPTION ++\fBgrub-mkrescue\fR can be used to generate a rescue image with the GRUB bootloader. ++ ++.SH OPTIONS ++.TP ++\fB--output\fR=\fIFILE\fR ++Write the generated file to \fIFILE\fR. The default is to write to standard output. ++ ++.TP ++\fB--modules\fR=\fIMODULES\fR ++Pre-load modules specified by \fIMODULES\fR. ++ ++.TP ++\fB--install-modules\fR=\fIMODULES\fR ++Install only \fIMODULES\fR and their dependencies. The default is to install all available modules. ++ ++.TP ++\fB--themes\fR=\fITHEMES\fR ++Install \fITHEMES\fR. The default is to install the \fIstarfield\fR theme, if available. ++ ++.TP ++\fB--fonts\fR=\fIFONTS\fR ++Install \fIFONTS\fR. The default is to install the \fIunicode\fR font. ++ ++.TP ++\fB--locales\fR=\fILOCALES\fR ++Install only locales listed in \fILOCALES\fR. The default is to install all available locales. ++ ++.TP ++\fB--compress\fR[=\fIno\fR,\fIxz\fR,\fIgz\fR,\fIlzo\fR] ++Compress GRUB files using the specified compression algorithm. ++ ++.TP ++\fB--directory\fR=\fIDIR\fR ++Use images and modules in \fIDIR\fR. ++ ++.TP ++\fB--grub-mkimage\fR=\fIFILE\fR ++Use \fIFILE\fR as \fBgrub-mkimage\fR(1). The default is \fI/usr/bin/grub-mkimage\fR. ++ ++.TP ++\fB--rom-directory\fR=\fIDIR\fR ++Save ROM images in \fIDIR\fR. ++ ++.TP ++\fB--xorriso\fR=\fIFILE\fR ++Use \fIFILE\fR as \fBxorriso\fI. ++ ++.TP ++\fB--grub-glue-efi\fR=\fIFILE\fR ++Use \fIFILE\fR as \fBgrub-glue-efi\fR(3). ++ ++.TP ++\fB--grub-render-label\fR=\fIFILE\fR ++Use \fIFILE\fR as \fBgrub-render-label\fR(3). ++ ++.TP ++\fB--label-font\fR=\fIFILE\fR ++Use \fIFILE\fR as the font file for generated labels. ++ ++.TP ++\fB--label-color\fR=\fICOLOR\fR ++Use \fICOLOR\fI as the color for generated labels. ++ ++.TP ++\fB--label-bgcolor\fR=\fICOLOR\fR ++Use \fICOLOR\fR as the background color for generated labels. ++ ++.TP ++\fB--product-name\fR=\fISTRING\fR ++Use \fISTRING\fR as the product name in generated labels. ++ ++.TP ++\fB--product-version\fR=\fISTRING\fR ++Use \fISTRING\fR as the product version in generated labels. ++ ++.TP ++\fB--sparc-boot\fR ++Enable booting the SPARC platform. This disables HFS+, APM, ARCS, and "boot as disk image" on the \fIi386-pc\fR target platform. ++ ++.TP ++\fB--arcs-boot\fR ++Enable ARCS booting. This is typically for big-endian MIPS machines, and disables HFS+, APM, sparc64, and "boot as disk image" on the \fIi386-pc\fR target platform. ++ ++.TP ++\fB--\fR ++All options after a \fB--\fR will be passed directly to xorriso's command line when generating the image. ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-mkstandalone.1 b/util/grub-mkstandalone.1 +new file mode 100644 +index 00000000000..ba2d2bdf279 +--- /dev/null ++++ b/util/grub-mkstandalone.1 +@@ -0,0 +1,100 @@ ++.TH GRUB-MKSTANDALONE 3 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-mkstandalone\fR \(em Generate a standalone image in the selected format. ++ ++.SH SYNOPSIS ++\fBgrub-mkstandalone\fR [-o | --output=\fIFILE\fR] [-O | --format=\fIFORMAT\fR] ++.RS 19 ++[-C | --compression=(\fIxz\fR|\fInone\fR|\fIauto\fR)] ++.RE ++.RS 19 ++[--modules=\fIMODULES\fR] [--install-modules=\fIMODULES\fR] ++.RE ++.RS 19 ++[--themes=\fITHEMES\fR] [--fonts=\fIFONTS\fR] ++.RE ++.RS 19 ++[--locales=\fILOCALES\fR] [--compress[=\fIno\fR,\fIxz\fR,\fIgz\fR,\fIlzo\fR]] ++.RE ++.RS 19 ++[-d | --directory=\fIDIR\fR] [--grub-mkimage=\fIFILE\fR] ++.RE ++.RS 19 ++\fISOURCE...\fR ++ ++.SH DESCRIPTION ++ ++.SH OPTIONS ++.TP ++--output=\fIFILE\fR ++Write the generated file to \fIFILE\fR. The default is to write to standard output. ++ ++.TP ++--format=\fIFORMAT\fR ++Generate an image in the specified \fIFORMAT\fR. Valid values are: ++.RS ++.RS 4 ++.P ++i386-coreboot, ++i386-multiboot, ++i386-pc, ++i386-pc-pxe, ++i386-efi, ++i386-ieee1275, ++i386-qemu, ++x86_64-efi, ++mipsel-yeeloong-flash, ++mipsel-fuloong2f-flash, ++mipself-loongson-elf, ++powerpc-ieee1275, ++sparc64-ieee1275-raw, ++sparc64-ieee1275-cdcore, ++sparc64-ieee1275-aout, ++ia64-efi, ++mips-arc, ++mipsel-arc, ++mipsel-qemu_mips-elf, ++mips-qemu_mips-flash, ++mipsel-qemu_mips-flash, ++mips-qemu_mips-elf ++.RE ++.RE ++ ++.TP ++--compression=(\fIxz\fR|\fInone\fR|\fIauto\fR) ++Use one of \fIxz\fR, \fInone\fR, or \fIauto\fR as the compression method for the core image. ++ ++.TP ++--modules=\fIMODULES\fR ++Pre-load modules specified by \fIMODULES\fR. ++ ++.TP ++--install-modules=\fIMODULES\fR ++Install only \fIMODULES\fR and their dependencies. The default is to install all available modules. ++ ++.TP ++--themes=\fITHEMES\fR ++Install \fITHEMES\fR. The default is to install the \fIstarfield\fR theme, if available. ++ ++.TP ++--fonts=\fIFONTS\fR ++Install \fIFONTS\fR. The default is to install the \fIunicode\fR font. ++ ++.TP ++--locales=\fILOCALES\fR ++Install only locales listed in \fILOCALES\fR. The default is to install all available locales. ++ ++.TP ++--compress[=\fIno\fR,\fIxz\fR,\fIgz\fR,\fIlzo\fR] ++Compress GRUB files using the specified compression algorithm. ++ ++.TP ++--directory=\fIDIR\fR ++Use images and modules in \fIDIR\fR. ++ ++.TP ++--grub-mkimage=\fIFILE\fR ++Use \fIFILE\fR as \fBgrub-mkimage\fR. The default is \fI/usr/bin/grub-mkimage\fR. ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-ofpathname.8 b/util/grub-ofpathname.8 +new file mode 100644 +index 00000000000..bf3743aeba1 +--- /dev/null ++++ b/util/grub-ofpathname.8 +@@ -0,0 +1,12 @@ ++.TH GRUB-OFPATHNAME 3 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-ofpathname\fR \(em Generate an IEEE-1275 device path for a specified device. ++ ++.SH SYNOPSIS ++\fBgrub-ofpathname\fR \fIDEVICE\fR ++ ++.SH DESCRIPTION ++\fBgrub-ofpathname\fR generates an IEEE-1275 device path for the specified \fIDEVICE\fR. ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-probe.8 b/util/grub-probe.8 +new file mode 100644 +index 00000000000..04e26c832bb +--- /dev/null ++++ b/util/grub-probe.8 +@@ -0,0 +1,80 @@ ++.TH GRUB-PROBE 3 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-probe\fR \(em Probe device information for a given path. ++ ++.SH SYNOPSIS ++\fBgrub-probe\fR \[-d | --device] [-m | --device-map=\fIFILE\fR] ++.RS 12 ++[-t | --target=(fs|fs_uuid|fs_label|drive|device|partmap| ++.RE ++.RS 28 ++abstraction|cryptodisk_uuid| ++.RE ++.RS 28 ++msdos_parttype)] ++.RE ++.RS 12 ++[-v | --verbose] (PATH|DEVICE) ++ ++.SH DESCRIPTION ++\fBgrub-probe\fR probes a path or device for filesystem and related information. ++ ++.SH OPTIONS ++.TP ++--device ++Final option represents a \fIDEVICE\fR, rather than a filesystem \fIPATH\fR. ++.TP ++--device-map=\fIFILE\fR ++Use \fIFILE\fR as the device map. The default value is \fI/boot/grub/device.map\fR. ++ ++.TP ++--target=(fs|fs_uuid|fs_label|drive|device|partmap|msdos_parttype) ++Select among various output definitions. The default is \fIfs\fR. ++.RS ++.TP ++\fIfs\fR ++filesystem module ++ ++.TP ++\fIfs_uuid\fR ++filesystem UUID ++ ++.TP ++\fIfs_label\fR ++filesystem label ++ ++.TP ++\fIdrive\fR ++GRUB drive name ++ ++.TP ++\fIdevice\fR ++System device ++ ++.TP ++\fIpartmap\fR ++partition map module ++ ++.TP ++\fIabstraction\fR ++abstraction module ++ ++.TP ++\fIcryptodisk_uuid\fR ++cryptographic container ++ ++.TP ++\fImsdos_partmap\fR ++MS-DOS partition map ++.RE ++ ++.TP ++--verbose ++Print verbose output. ++ ++.TP ++(\fIPATH\fR|\fIDEVICE\fR) ++If --device is passed, a block \fIDEVICE\fR. Otherwise, the \fIPATH\fR of a file on the filesystem. ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-reboot.8 b/util/grub-reboot.8 +new file mode 100644 +index 00000000000..faa5e4eece2 +--- /dev/null ++++ b/util/grub-reboot.8 +@@ -0,0 +1,21 @@ ++.TH GRUB-REBOOT 3 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-reboot\fR \(em Set the default boot menu entry for the next boot only. ++ ++.SH SYNOPSIS ++\fBgrub-reboot\fR [--boot-directory=\fIDIR\fR] \fIMENU_ENTRY\fR ++ ++.SH DESCRIPTION ++\fBgrub-reboot\fR sets the default boot menu entry for the next boot, but not further boots after that. This command only works for GRUB configuration files created with \fIGRUB_DEFAULT=saved\fR in \fI/etc/default/grub\fR. ++ ++.SH OPTIONS ++.TP ++--boot-directory=\fIDIR\fR ++Find GRUB images under \fIDIR/grub\fR. The default value is \fI/boot\fR, resulting in grub images being search for at \fI/boot/grub\fR. ++ ++.TP ++\fIMENU_ENTRY\fR ++A number, a menu item title or a menu item identifier. ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-render-label.1 b/util/grub-render-label.1 +new file mode 100644 +index 00000000000..4d51c8abf01 +--- /dev/null ++++ b/util/grub-render-label.1 +@@ -0,0 +1,51 @@ ++.TH GRUB-RENDER-LABEL 3 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-render-label\fR \(em Render an Apple disk label. ++ ++.SH SYNOPSIS ++\fBgrub-render-label\fR [-b | --bgcolor=\fICOLOR\fR] [-c | --color=\fICOLOR\fR] ++.RS 19 ++[-f | --font=\fIFILE\fR] [-i | --input=\fIFILE\fR] ++.RE ++.RS 19 ++[-o | --output=\fIFILE\fR] [-t | --text=\fISTRING\fR] ++.RE ++.RS 19 ++[-v | --verbose] ++ ++.SH DESCRIPTION ++\fBgrub-render-label\fR renders an Apple disk label (.disk_label) file. ++ ++ ++.SH OPTIONS ++.TP ++\fB--color\fR=\fICOLOR\fR ++Use \fICOLOR\fI as the color for generated labels. ++ ++.TP ++\fB--bgcolor\fR=\fICOLOR\fR ++Use \fICOLOR\fR as the background color for generated labels. ++ ++.TP ++\fB--font\fR=\fIFILE\fR ++Use \fIFILE\fR as the font file for generated labels. ++ ++.TP ++--input=\fIFILE\fR ++Read input text from \fIFILE\fR. ++ ++.TP ++--output=\fIFILE\fR ++Render output to \fIFILE\fR. ++ ++.TP ++--text=\fISTRING\fR ++Use \fISTRING\fR as input text. ++ ++.TP ++--verbose ++Print verbose output. ++ ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-script-check.1 b/util/grub-script-check.1 +new file mode 100644 +index 00000000000..0f1f625b05d +--- /dev/null ++++ b/util/grub-script-check.1 +@@ -0,0 +1,21 @@ ++.TH GRUB-SCRIPT-CHECK 3 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-script-check\fR \(em Check GRUB configuration file for syntax errors. ++ ++.SH SYNOPSIS ++\fBgrub-script-check\fR [-v | --verbose] \fIPATH\fR ++ ++.SH DESCRIPTION ++\fBgrub-script-check\fR verifies that a specified GRUB configuration file does not contain syntax errors. ++ ++.SH OPTIONS ++.TP ++--verbose ++Print verbose output. ++ ++.TP ++\fIPATH\fR ++Path of the file to use as input. ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-set-default.8 b/util/grub-set-default.8 +new file mode 100644 +index 00000000000..a96265a1509 +--- /dev/null ++++ b/util/grub-set-default.8 +@@ -0,0 +1,21 @@ ++.TH GRUB-SET-DEFAULT 1 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-set-default\fR \(em Set the default boot menu entry for GRUB. ++ ++.SH SYNOPSIS ++\fBgrub-set-default\fR [--boot-directory=\fIDIR\fR] \fIMENU_ENTRY\fR ++ ++.SH DESCRIPTION ++\fBgrub-set-default\fR sets the default boot menu entry for all subsequent boots. This command only works for GRUB configuration files created with \fIGRUB_DEFAULT=saved\fR in \fI/etc/default/grub\fR. ++ ++.SH OPTIONS ++.TP ++--boot-directory=\fIDIR\fR ++Find GRUB images under \fIDIR/grub\fR. The default value is \fI/boot\fR, resulting in grub images being search for at \fI/boot/grub\fR. ++ ++.TP ++\fIMENU_ENTRY\fR ++A number, a menu item title or a menu item identifier. ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-sparc64-setup.8 b/util/grub-sparc64-setup.8 +new file mode 100644 +index 00000000000..37ea2dd5eaa +--- /dev/null ++++ b/util/grub-sparc64-setup.8 +@@ -0,0 +1,12 @@ ++.TH GRUB-SPARC64-SETUP 3 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-sparc64-setup\fR \(em Set up a device to boot a sparc64 GRUB image. ++ ++.SH SYNOPSIS ++\fBgrub-sparc64-setup\fR [OPTIONS]. ++ ++.SH DESCRIPTION ++You should not normally run this program directly. Use grub-install instead. ++ ++.SH SEE ALSO ++.BR "info grub" diff --git a/SOURCES/0131-use-fw_path-prefix-when-fallback-searching-for-grub-.patch b/SOURCES/0131-use-fw_path-prefix-when-fallback-searching-for-grub-.patch new file mode 100644 index 0000000..c5899aa --- /dev/null +++ b/SOURCES/0131-use-fw_path-prefix-when-fallback-searching-for-grub-.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Fedora Ninjas +Date: Wed, 19 Feb 2014 15:58:43 -0500 +Subject: [PATCH] use fw_path prefix when fallback searching for grub config + +When PXE booting via UEFI firmware, grub was searching for grub.cfg +in the fw_path directory where the grub application was found. If +that didn't exist, a fallback search would look for config file names +based on MAC and IP address. However, the search would look in the +prefix directory which may not be the same fw_path. This patch +changes that behavior to use the fw_path directory for the fallback +search. Only if fw_path is NULL will the prefix directory be searched. + +Signed-off-by: Mark Salter +--- + grub-core/normal/main.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c +index f66c03c4c6e..5e2ac150e12 100644 +--- a/grub-core/normal/main.c ++++ b/grub-core/normal/main.c +@@ -343,7 +343,7 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), + char *config; + const char *prefix, *fw_path; + +- fw_path = grub_env_get ("fw_path"); ++ prefix = fw_path = grub_env_get ("fw_path"); + if (fw_path) + { + config = grub_xasprintf ("%s/grub.cfg", fw_path); +@@ -366,7 +366,8 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), + } + } + +- prefix = grub_env_get ("prefix"); ++ if (! prefix) ++ prefix = grub_env_get ("prefix"); + if (prefix) + { + grub_size_t config_len; diff --git a/SOURCES/0132-Try-mac-guid-etc-before-grub.cfg-on-tftp-config-file.patch b/SOURCES/0132-Try-mac-guid-etc-before-grub.cfg-on-tftp-config-file.patch new file mode 100644 index 0000000..31bd38c --- /dev/null +++ b/SOURCES/0132-Try-mac-guid-etc-before-grub.cfg-on-tftp-config-file.patch @@ -0,0 +1,111 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 6 Mar 2014 11:51:33 -0500 +Subject: [PATCH] Try mac/guid/etc before grub.cfg on tftp config files. + +Signed-off-by: Peter Jones +--- + grub-core/normal/main.c | 80 ++++++++++++++++++++++++++----------------------- + 1 file changed, 43 insertions(+), 37 deletions(-) + +diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c +index 5e2ac150e12..4190985ad37 100644 +--- a/grub-core/normal/main.c ++++ b/grub-core/normal/main.c +@@ -341,53 +341,59 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), + /* Guess the config filename. It is necessary to make CONFIG static, + so that it won't get broken by longjmp. */ + char *config; +- const char *prefix, *fw_path; +- +- prefix = fw_path = grub_env_get ("fw_path"); +- if (fw_path) +- { +- config = grub_xasprintf ("%s/grub.cfg", fw_path); +- if (config) +- { +- grub_file_t file; +- +- file = grub_file_open (config); +- if (file) +- { +- grub_file_close (file); +- grub_enter_normal_mode (config); +- } +- else +- { +- /* Ignore all errors. */ +- grub_errno = 0; +- } +- grub_free (config); +- } +- } ++ const char *prefix; + ++ prefix = grub_env_get ("fw_path"); + if (! prefix) + prefix = grub_env_get ("prefix"); ++ + if (prefix) +- { +- grub_size_t config_len; +- config_len = grub_strlen (prefix) + +- sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"); +- config = grub_malloc (config_len); ++ { ++ if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0) ++ { ++ grub_size_t config_len; ++ config_len = grub_strlen (prefix) + ++ sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"); ++ config = grub_malloc (config_len); + +- if (! config) +- goto quit; ++ if (! config) ++ goto quit; + +- grub_snprintf (config, config_len, "%s/grub.cfg", prefix); ++ grub_snprintf (config, config_len, "%s/grub.cfg", prefix); + +- if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0) +- grub_net_search_configfile (config); ++ grub_net_search_configfile (config); + +- grub_enter_normal_mode (config); +- grub_free (config); ++ grub_enter_normal_mode (config); ++ grub_free (config); ++ config = NULL; ++ } ++ ++ if (!config) ++ { ++ config = grub_xasprintf ("%s/grub.cfg", prefix); ++ if (config) ++ { ++ grub_file_t file; ++ ++ file = grub_file_open (config); ++ if (file) ++ { ++ grub_file_close (file); ++ grub_enter_normal_mode (config); ++ } ++ else ++ { ++ /* Ignore all errors. */ ++ grub_errno = 0; ++ } ++ grub_free (config); ++ } ++ } + } + else +- grub_enter_normal_mode (0); ++ { ++ grub_enter_normal_mode (0); ++ } + } + else + grub_enter_normal_mode (argv[0]); diff --git a/SOURCES/0133-trim-arp-packets-with-abnormal-size.patch b/SOURCES/0133-trim-arp-packets-with-abnormal-size.patch new file mode 100644 index 0000000..944050f --- /dev/null +++ b/SOURCES/0133-trim-arp-packets-with-abnormal-size.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paulo Flabiano Smorigo +Date: Wed, 5 Feb 2014 09:42:42 -0200 +Subject: [PATCH] trim arp packets with abnormal size + +GRUB uses arp request to create the arp response. If the incoming packet +is foobared, GRUB needs to trim the arp response packet before sending it. +--- + grub-core/net/arp.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c +index d62d0cc1e01..77581f4b29a 100644 +--- a/grub-core/net/arp.c ++++ b/grub-core/net/arp.c +@@ -162,6 +162,12 @@ grub_net_arp_receive (struct grub_net_buff *nb, + if (grub_net_addr_cmp (&inf->address, &target_addr) == 0 + && grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST) + { ++ if ((nb->tail - nb->data) > 50) ++ { ++ grub_dprintf ("net", "arp packet with abnormal size (%ld bytes).\n", ++ nb->tail - nb->data); ++ nb->tail = nb->data + 50; ++ } + grub_net_link_level_address_t target; + /* We've already checked that pln is either 4 or 16. */ + char tmp[16]; diff --git a/SOURCES/0134-Fix-convert-function-to-support-NVMe-devices.patch b/SOURCES/0134-Fix-convert-function-to-support-NVMe-devices.patch new file mode 100644 index 0000000..d3dc3d3 --- /dev/null +++ b/SOURCES/0134-Fix-convert-function-to-support-NVMe-devices.patch @@ -0,0 +1,56 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 18 Feb 2014 11:34:00 -0500 +Subject: [PATCH] Fix convert function to support NVMe devices + +This is adapted from the patch at +https://bugzilla.redhat.com/show_bug.cgi?id=1019660 , which is against +the now very old version of convert_system_partition_to_system_disk(). + +As such, it certainly not the right thing for upstream, but should +function for now. + +Resolves: rhbz#1019660 + +Signed-off-by: Peter Jones +--- + util/getroot.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/util/getroot.c b/util/getroot.c +index 3958105d819..e70061099b3 100644 +--- a/util/getroot.c ++++ b/util/getroot.c +@@ -152,6 +152,7 @@ convert_system_partition_to_system_disk (const char *os_dev, int *is_part) + { + #if GRUB_UTIL_FD_STAT_IS_FUNCTIONAL + struct stat st; ++ char *path = xmalloc(PATH_MAX); + + if (stat (os_dev, &st) < 0) + { +@@ -164,6 +165,24 @@ convert_system_partition_to_system_disk (const char *os_dev, int *is_part) + + *is_part = 0; + ++ if (realpath(os_dev, path)) ++ { ++ if ((strncmp ("/dev/nvme", path, 9) == 0)) ++ { ++ char *p = path + 5; ++ p = strchr(p, 'p'); ++ if (p) ++ { ++ *is_part = 1; ++ *p = '\0'; ++ } ++ return path; ++ } ++ } ++ ++ grub_free (path); ++ *is_part = 0; ++ + if (grub_util_device_is_mapped_stat (&st)) + return grub_util_devmapper_part_to_disk (&st, is_part, os_dev); + diff --git a/SOURCES/0135-Fix-bad-test-on-GRUB_DISABLE_SUBMENU.patch b/SOURCES/0135-Fix-bad-test-on-GRUB_DISABLE_SUBMENU.patch new file mode 100644 index 0000000..3e50793 --- /dev/null +++ b/SOURCES/0135-Fix-bad-test-on-GRUB_DISABLE_SUBMENU.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Prarit Bhargava +Date: Wed, 12 Mar 2014 10:58:16 -0400 +Subject: [PATCH] Fix bad test on GRUB_DISABLE_SUBMENU. + +The file /etc/grub.d/10_linux does + +if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xy ]; then + +when it should do + +if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xtrue ]; then + +which results in submenus in /boot/grub2/grub.cfg when +GRUB_DISABLE_SUBMENU="yes". + +Resolves: rhbz#1063414 +--- + util/grub.d/10_linux.in | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index 136abd7a6e3..767093c636a 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -255,7 +255,11 @@ while [ "x$list" != "x" ] ; do + linux_root_device_thisversion=${GRUB_DEVICE} + fi + +- if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xy ]; then ++ if [ "x${GRUB_DISABLE_SUBMENU}" = "xyes" ] || [ "x${GRUB_DISABLE_SUBMENU}" = "xy" ]; then ++ GRUB_DISABLE_SUBMENU="true" ++ fi ++ ++ if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xtrue ]; then + linux_entry "${OS}" "${version}" simple \ + "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" + diff --git a/SOURCES/0136-Switch-to-use-APM-Mustang-device-tree-for-hardware-t.patch b/SOURCES/0136-Switch-to-use-APM-Mustang-device-tree-for-hardware-t.patch new file mode 100644 index 0000000..2c2a1c3 --- /dev/null +++ b/SOURCES/0136-Switch-to-use-APM-Mustang-device-tree-for-hardware-t.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Fedora Ninjas +Date: Mon, 10 Feb 2014 16:13:10 -0500 +Subject: [PATCH] Switch to use APM Mustang device tree, for hardware testing. + +Signed-off-by: David A. Marlin +--- + util/grub.d/10_linux.in | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index 767093c636a..3722c1ea263 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -228,8 +228,8 @@ while [ "x$list" != "x" ] ; do + + fdt= + for i in "dtb-${version}" "dtb-${alt_version}"; do +- if test -e "${dirname}/${i}/foundation-v8.dtb" ; then +- fdt="${i}/foundation-v8.dtb" ++ if test -e "${dirname}/${i}/apm-mustang.dtb" ; then ++ fdt="${i}/apm-mustang.dtb" + break + fi + done diff --git a/SOURCES/0137-Use-the-default-device-tree-from-the-grub-default-fi.patch b/SOURCES/0137-Use-the-default-device-tree-from-the-grub-default-fi.patch new file mode 100644 index 0000000..418a3a6 --- /dev/null +++ b/SOURCES/0137-Use-the-default-device-tree-from-the-grub-default-fi.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Fedora Ninjas +Date: Wed, 12 Feb 2014 14:54:04 -0500 +Subject: [PATCH] Use the default device tree from the grub default file + +instead of hardcoding a value. + +Signed-off-by: David A. Marlin +--- + util/grub-mkconfig.in | 3 ++- + util/grub.d/10_linux.in | 4 ++-- + 2 files changed, 4 insertions(+), 3 deletions(-) + +diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in +index b00f9e61f40..beb22deee79 100644 +--- a/util/grub-mkconfig.in ++++ b/util/grub-mkconfig.in +@@ -224,7 +224,8 @@ export GRUB_DEFAULT \ + GRUB_ENABLE_CRYPTODISK \ + GRUB_BADRAM \ + GRUB_OS_PROBER_SKIP_LIST \ +- GRUB_DISABLE_SUBMENU ++ GRUB_DISABLE_SUBMENU \ ++ GRUB_DEFAULT_DTB + + if test "x${grub_cfg}" != "x"; then + rm -f "${grub_cfg}.new" +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index 3722c1ea263..8782d8c67cf 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -228,8 +228,8 @@ while [ "x$list" != "x" ] ; do + + fdt= + for i in "dtb-${version}" "dtb-${alt_version}"; do +- if test -e "${dirname}/${i}/apm-mustang.dtb" ; then +- fdt="${i}/apm-mustang.dtb" ++ if test -f "${dirname}/${i}/${GRUB_DEFAULT_DTB}" ; then ++ fdt="${i}/${GRUB_DEFAULT_DTB}" + break + fi + done diff --git a/SOURCES/0138-reopen-SNP-protocol-for-exclusive-use-by-grub.patch b/SOURCES/0138-reopen-SNP-protocol-for-exclusive-use-by-grub.patch new file mode 100644 index 0000000..09f60d8 --- /dev/null +++ b/SOURCES/0138-reopen-SNP-protocol-for-exclusive-use-by-grub.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Fedora Ninjas +Date: Sat, 15 Feb 2014 15:10:22 -0500 +Subject: [PATCH] reopen SNP protocol for exclusive use by grub + +--- + grub-core/net/drivers/efi/efinet.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index 2b344d6ef78..a6e4c7992f7 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -223,6 +223,7 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + { + struct grub_net_card *card; + grub_efi_device_path_t *dp; ++ grub_efi_simple_network_t *net; + + dp = grub_efi_get_device_path (hnd); + if (! dp) +@@ -250,6 +251,21 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + &pxe_mode->dhcp_ack, + sizeof (pxe_mode->dhcp_ack), + 1, device, path); ++ net = grub_efi_open_protocol (card->efi_handle, &net_io_guid, ++ GRUB_EFI_OPEN_PROTOCOL_BY_EXCLUSIVE); ++ if (net) { ++ if (net->mode->state == GRUB_EFI_NETWORK_STOPPED ++ && efi_call_1 (net->start, net) != GRUB_EFI_SUCCESS) ++ continue; ++ ++ if (net->mode->state == GRUB_EFI_NETWORK_STOPPED) ++ continue; ++ ++ if (net->mode->state == GRUB_EFI_NETWORK_STARTED ++ && efi_call_3 (net->initialize, net, 0, 0) != GRUB_EFI_SUCCESS) ++ continue; ++ card->efi_net = net; ++ } + return; + } + } diff --git a/SOURCES/0139-Reduce-timer-event-frequency-by-10.patch b/SOURCES/0139-Reduce-timer-event-frequency-by-10.patch new file mode 100644 index 0000000..bb614d3 --- /dev/null +++ b/SOURCES/0139-Reduce-timer-event-frequency-by-10.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Salter +Date: Thu, 20 Feb 2014 12:54:52 -0500 +Subject: [PATCH] Reduce timer event frequency by 10 + +Timer event to keep grub msec counter was running at 1000HZ. This was too +fast for UEFI timer driver and resulted in a 10x slowdown in grub time +versus wallclock. Reduce the timer event frequency and increase tick +increment accordingly to keep better time. + +Signed-off-by: Mark Salter +--- + grub-core/kern/arm/efi/init.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/grub-core/kern/arm/efi/init.c b/grub-core/kern/arm/efi/init.c +index a6ae03475cc..0c17d8390fa 100644 +--- a/grub-core/kern/arm/efi/init.c ++++ b/grub-core/kern/arm/efi/init.c +@@ -38,7 +38,7 @@ static void + increment_timer (grub_efi_event_t event __attribute__ ((unused)), + void *context __attribute__ ((unused))) + { +- tmr++; ++ tmr += 10; + } + + void +@@ -52,7 +52,7 @@ grub_machine_init (void) + + efi_call_5 (b->create_event, GRUB_EFI_EVT_TIMER | GRUB_EFI_EVT_NOTIFY_SIGNAL, + GRUB_EFI_TPL_CALLBACK, increment_timer, NULL, &tmr_evt); +- efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_PERIODIC, 10000); ++ efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_PERIODIC, 100000); + + grub_install_get_time_ms (grub_efi_get_time_ms); + } diff --git a/SOURCES/0140-always-return-error-to-UEFI.patch b/SOURCES/0140-always-return-error-to-UEFI.patch new file mode 100644 index 0000000..4720fba --- /dev/null +++ b/SOURCES/0140-always-return-error-to-UEFI.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Fedora Ninjas +Date: Wed, 26 Feb 2014 21:49:12 -0500 +Subject: [PATCH] always return error to UEFI + +--- + grub-core/kern/efi/efi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c +index cd839cc988a..1a8dba531b6 100644 +--- a/grub-core/kern/efi/efi.c ++++ b/grub-core/kern/efi/efi.c +@@ -158,7 +158,7 @@ grub_exit (void) + { + grub_efi_fini (); + efi_call_4 (grub_efi_system_table->boot_services->exit, +- grub_efi_image_handle, GRUB_EFI_SUCCESS, 0, 0); ++ grub_efi_image_handle, GRUB_EFI_LOAD_ERROR, 0, 0); + for (;;) ; + } + diff --git a/SOURCES/0141-Add-powerpc-little-endian-ppc64le-flags.patch b/SOURCES/0141-Add-powerpc-little-endian-ppc64le-flags.patch new file mode 100644 index 0000000..7920668 --- /dev/null +++ b/SOURCES/0141-Add-powerpc-little-endian-ppc64le-flags.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paulo Flabiano Smorigo +Date: Wed, 13 Aug 2014 18:59:58 +0000 +Subject: [PATCH] Add powerpc little-endian (ppc64le) flags + +libgcc dependency was removed *just* for this target because +the distros that use ppc64el doesn't have 32-bit support on it. + +* configure.ac: Add targets for powerpc64el and skip libgcc. +* Makefile.am: Likewise. +--- + configure.ac | 17 +++++++++++++++-- + grub-core/Makefile.am | 2 ++ + 2 files changed, 17 insertions(+), 2 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 2632e2dad9b..53fd7c73ee6 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -142,6 +142,7 @@ if test "x$with_platform" = x; then + x86_64-*) platform=pc ;; + powerpc-*) platform=ieee1275 ;; + powerpc64-*) platform=ieee1275 ;; ++ powerpc64le-*) platform=ieee1275 ;; + sparc64-*) platform=ieee1275 ;; + mipsel-*) platform=loongson ;; + mips-*) platform=arc ;; +@@ -160,6 +161,7 @@ case "$target_cpu"-"$platform" in + x86_64-xen) ;; + x86_64-*) target_cpu=i386 ;; + powerpc64-ieee1275) target_cpu=powerpc ;; ++ powerpc64le-ieee1275) target_cpu=powerpc ;; + esac + + # Check if the platform is supported, make final adjustments. +@@ -604,6 +606,13 @@ if test "x$target_cpu" = xi386 && test "x$platform" != xemu; then + TARGET_CFLAGS="$TARGET_CFLAGS -march=i386" + fi + ++if test x$target_cpu = xpowerpc && test x$ac_cv_c_bigendian = xno; then ++ LD_FORCE_LE=1 ++ TARGET_CFLAGS="$TARGET_CFLAGS -mbig-endian -DNO_LIBGCC=1" ++ TARGET_CCASFLAGS="$TARGET_CCASFLAGS -mbig-endian" ++ TARGET_LDFLAGS="$TARGET_LDFLAGS -static -mbig-endian" ++fi ++ + if test "x$target_m32" = x1; then + # Force 32-bit mode. + TARGET_CFLAGS="$TARGET_CFLAGS -m32" +@@ -1047,7 +1056,8 @@ else + CFLAGS="$TARGET_CFLAGS -nostdlib -Wno-error" + fi + CPPFLAGS="$TARGET_CPPFLAGS" +-if test x$target_cpu = xi386 || test x$target_cpu = xx86_64 || test "x$grub_cv_cc_target_clang" = xyes ; then ++if test x$target_cpu = xi386 || test x$target_cpu = xx86_64 || test "x$grub_cv_cc_target_clang" = xyes \ ++ || ( test x$target_cpu = xpowerpc && test x$ac_cv_c_bigendian = xno ); then + TARGET_LIBGCC= + else + TARGET_LIBGCC=-lgcc +@@ -1631,7 +1641,9 @@ if test x"$enable_werror" != xno ; then + HOST_CFLAGS="$HOST_CFLAGS -Werror" + fi + +-if test "x$grub_cv_cc_target_clang" = xno; then ++# if not clang or power LE, use static libgcc ++if test "x$grub_cv_cc_target_clang" = xno \ ++ || ! ( test x$target_cpu = xpowerpc && test x$ac_cv_c_bigendian = xno ); then + TARGET_LDFLAGS_STATIC_LIBGCC="-static-libgcc" + else + TARGET_LDFLAGS_STATIC_LIBGCC= +@@ -1694,6 +1706,7 @@ AM_CONDITIONAL([COND_mips_arc], [test "(" x$target_cpu = xmips -o x$target_cpu = + AM_CONDITIONAL([COND_sparc64_ieee1275], [test x$target_cpu = xsparc64 -a x$platform = xieee1275]) + AM_CONDITIONAL([COND_sparc64_emu], [test x$target_cpu = xsparc64 -a x$platform = xemu]) + AM_CONDITIONAL([COND_powerpc_ieee1275], [test x$target_cpu = xpowerpc -a x$platform = xieee1275]) ++AM_CONDITIONAL([COND_powerpc_le], [test x$target_cpu = xpowerpc -a x$ac_cv_c_bigendian = xno]) + AM_CONDITIONAL([COND_mips], [test x$target_cpu = xmips -o x$target_cpu = xmipsel]) + AM_CONDITIONAL([COND_mipsel], [test x$target_cpu = xmipsel]) + AM_CONDITIONAL([COND_mipseb], [test x$target_cpu = xmips]) +diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am +index 5c087c83b8f..cb7fd9f98e8 100644 +--- a/grub-core/Makefile.am ++++ b/grub-core/Makefile.am +@@ -84,8 +84,10 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h + if !COND_clang ++if !COND_powerpc_le + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h + endif ++endif + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h + + if COND_i386_pc diff --git a/SOURCES/0142-Files-reorganization-and-include-some-libgcc-fuction.patch b/SOURCES/0142-Files-reorganization-and-include-some-libgcc-fuction.patch new file mode 100644 index 0000000..05cbdd3 --- /dev/null +++ b/SOURCES/0142-Files-reorganization-and-include-some-libgcc-fuction.patch @@ -0,0 +1,436 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paulo Flabiano Smorigo +Date: Wed, 13 Aug 2014 19:00:19 +0000 +Subject: [PATCH] Files reorganization and include some libgcc fuctions + +As we avoid libgcc dependency for powerpc64el, we moved some functions +to other files and add the necessary ones. + +* Makefile.core.def: Include compiler-rt.S. +* misc.c: Add the necessary libgcc functions. +* compiler-rt.S: New file. +* libgcc.h: Move some content from here ... +* compiler.h: ... to here. + +Also-By: Brent Baude +Also-By: Vladimir 'phcoder' Serbinenko +--- + grub-core/Makefile.core.def | 1 + + grub-core/kern/misc.c | 107 ++++++++++++++++++++++++++++ + include/grub/compiler.h | 61 ++++++++++++++++ + include/grub/libgcc.h | 67 ------------------ + grub-core/kern/powerpc/compiler-rt.S | 130 +++++++++++++++++++++++++++++++++++ + 5 files changed, 299 insertions(+), 67 deletions(-) + create mode 100644 grub-core/kern/powerpc/compiler-rt.S + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 7bf1c8a5880..9ff9ae5a311 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -252,6 +252,7 @@ kernel = { + + powerpc_ieee1275 = kern/powerpc/cache.S; + powerpc_ieee1275 = kern/powerpc/dl.c; ++ powerpc_ieee1275 = kern/powerpc/compiler-rt.S; + + sparc64_ieee1275 = kern/sparc64/cache.S; + sparc64_ieee1275 = kern/sparc64/dl.c; +diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c +index a56cfe78994..a3e5056db3f 100644 +--- a/grub-core/kern/misc.c ++++ b/grub-core/kern/misc.c +@@ -1345,3 +1345,110 @@ grub_real_boot_time (const char *file, + grub_error_pop (); + } + #endif ++ ++#if defined (NO_LIBGCC) ++ ++/* Based on libgcc2.c from gcc suite. */ ++int ++__ucmpdi2 (grub_uint64_t a, grub_uint64_t b) ++{ ++ union component64 ac, bc; ++ ac.full = a; ++ bc.full = b; ++ ++ if (ac.high < bc.high) ++ return 0; ++ else if (ac.high > bc.high) ++ return 2; ++ ++ if (ac.low < bc.low) ++ return 0; ++ else if (ac.low > bc.low) ++ return 2; ++ return 1; ++} ++ ++ ++/* Based on libgcc2.c from gcc suite. */ ++grub_uint64_t ++__lshrdi3 (grub_uint64_t u, int b) ++{ ++ if (b == 0) ++ return u; ++ ++ const union component64 uu = {.full = u}; ++ const int bm = 32 - b; ++ union component64 w; ++ ++ if (bm <= 0) ++ { ++ w.high = 0; ++ w.low = (grub_uint32_t) uu.high >> -bm; ++ } ++ else ++ { ++ const grub_uint32_t carries = (grub_uint32_t) uu.high << bm; ++ ++ w.high = (grub_uint32_t) uu.high >> b; ++ w.low = ((grub_uint32_t) uu.low >> b) | carries; ++ } ++ ++ return w.full; ++} ++ ++/* Based on libgcc2.c from gcc suite. */ ++grub_uint64_t ++__ashrdi3 (grub_uint64_t u, int b) ++{ ++ if (b == 0) ++ return u; ++ ++ const union component64 uu = {.full = u}; ++ const int bm = 32 - b; ++ union component64 w; ++ ++ if (bm <= 0) ++ { ++ /* w.high = 1..1 or 0..0 */ ++ w.high = uu.high >> (32 - 1); ++ w.low = uu.high >> -bm; ++ } ++ else ++ { ++ const grub_uint32_t carries = (grub_uint32_t) uu.high << bm; ++ ++ w.high = uu.high >> b; ++ w.low = ((grub_uint32_t) uu.low >> b) | carries; ++ } ++ ++ return w.full; ++} ++ ++/* Based on libgcc2.c from gcc suite. */ ++grub_uint64_t ++__ashldi3 (grub_uint64_t u, int b) ++{ ++ if (b == 0) ++ return u; ++ ++ const union component64 uu = {.full = u}; ++ const int bm = 32 - b; ++ union component64 w; ++ ++ if (bm <= 0) ++ { ++ w.low = 0; ++ w.high = (grub_uint32_t) uu.low << -bm; ++ } ++ else ++ { ++ const grub_uint32_t carries = (grub_uint32_t) uu.low >> bm; ++ ++ w.low = (grub_uint32_t) uu.low << b; ++ w.high = ((grub_uint32_t) uu.high << b) | carries; ++ } ++ ++ return w.full; ++} ++ ++#endif +diff --git a/include/grub/compiler.h b/include/grub/compiler.h +index c9e1d7a73dc..a9a684ccba6 100644 +--- a/include/grub/compiler.h ++++ b/include/grub/compiler.h +@@ -48,4 +48,65 @@ + # define WARN_UNUSED_RESULT + #endif + ++#include "types.h" ++ ++union component64 ++{ ++ grub_uint64_t full; ++ struct ++ { ++#ifdef GRUB_CPU_WORDS_BIGENDIAN ++ grub_uint32_t high; ++ grub_uint32_t low; ++#else ++ grub_uint32_t low; ++ grub_uint32_t high; ++#endif ++ }; ++}; ++ ++#if defined (__powerpc__) ++grub_uint64_t EXPORT_FUNC (__lshrdi3) (grub_uint64_t u, int b); ++grub_uint64_t EXPORT_FUNC (__ashrdi3) (grub_uint64_t u, int b); ++grub_uint64_t EXPORT_FUNC (__ashldi3) (grub_uint64_t u, int b); ++int EXPORT_FUNC(__ucmpdi2) (grub_uint64_t a, grub_uint64_t b); ++void EXPORT_FUNC (_restgpr_14_x) (void); ++void EXPORT_FUNC (_restgpr_15_x) (void); ++void EXPORT_FUNC (_restgpr_16_x) (void); ++void EXPORT_FUNC (_restgpr_17_x) (void); ++void EXPORT_FUNC (_restgpr_18_x) (void); ++void EXPORT_FUNC (_restgpr_19_x) (void); ++void EXPORT_FUNC (_restgpr_20_x) (void); ++void EXPORT_FUNC (_restgpr_21_x) (void); ++void EXPORT_FUNC (_restgpr_22_x) (void); ++void EXPORT_FUNC (_restgpr_23_x) (void); ++void EXPORT_FUNC (_restgpr_24_x) (void); ++void EXPORT_FUNC (_restgpr_25_x) (void); ++void EXPORT_FUNC (_restgpr_26_x) (void); ++void EXPORT_FUNC (_restgpr_27_x) (void); ++void EXPORT_FUNC (_restgpr_28_x) (void); ++void EXPORT_FUNC (_restgpr_29_x) (void); ++void EXPORT_FUNC (_restgpr_30_x) (void); ++void EXPORT_FUNC (_restgpr_31_x) (void); ++void EXPORT_FUNC (_savegpr_14) (void); ++void EXPORT_FUNC (_savegpr_15) (void); ++void EXPORT_FUNC (_savegpr_16) (void); ++void EXPORT_FUNC (_savegpr_17) (void); ++void EXPORT_FUNC (_savegpr_18) (void); ++void EXPORT_FUNC (_savegpr_19) (void); ++void EXPORT_FUNC (_savegpr_20) (void); ++void EXPORT_FUNC (_savegpr_21) (void); ++void EXPORT_FUNC (_savegpr_22) (void); ++void EXPORT_FUNC (_savegpr_23) (void); ++void EXPORT_FUNC (_savegpr_24) (void); ++void EXPORT_FUNC (_savegpr_25) (void); ++void EXPORT_FUNC (_savegpr_26) (void); ++void EXPORT_FUNC (_savegpr_27) (void); ++void EXPORT_FUNC (_savegpr_28) (void); ++void EXPORT_FUNC (_savegpr_29) (void); ++void EXPORT_FUNC (_savegpr_30) (void); ++void EXPORT_FUNC (_savegpr_31) (void); ++ ++#endif ++ + #endif /* ! GRUB_COMPILER_HEADER */ +diff --git a/include/grub/libgcc.h b/include/grub/libgcc.h +index 8e93b6792d9..5bdb8fb5cb9 100644 +--- a/include/grub/libgcc.h ++++ b/include/grub/libgcc.h +@@ -16,73 +16,6 @@ + * along with GRUB. If not, see . + */ + +-/* We need to include config-util.h.in for HAVE_*. */ +-#ifndef __STDC_VERSION__ +-#define __STDC_VERSION__ 0 +-#endif +-#include +- +-/* On x86 these functions aren't really needed. Save some space. */ +-#if !defined (__i386__) && !defined (__x86_64__) +-# ifdef HAVE___ASHLDI3 +-void EXPORT_FUNC (__ashldi3) (void); +-# endif +-# ifdef HAVE___ASHRDI3 +-void EXPORT_FUNC (__ashrdi3) (void); +-# endif +-# ifdef HAVE___LSHRDI3 +-void EXPORT_FUNC (__lshrdi3) (void); +-# endif +-# ifdef HAVE___UCMPDI2 +-void EXPORT_FUNC (__ucmpdi2) (void); +-# endif +-# ifdef HAVE___BSWAPSI2 +-void EXPORT_FUNC (__bswapsi2) (void); +-# endif +-# ifdef HAVE___BSWAPDI2 +-void EXPORT_FUNC (__bswapdi2) (void); +-# endif +-#endif +- +-#ifdef HAVE__RESTGPR_14_X +-void EXPORT_FUNC (_restgpr_14_x) (void); +-void EXPORT_FUNC (_restgpr_15_x) (void); +-void EXPORT_FUNC (_restgpr_16_x) (void); +-void EXPORT_FUNC (_restgpr_17_x) (void); +-void EXPORT_FUNC (_restgpr_18_x) (void); +-void EXPORT_FUNC (_restgpr_19_x) (void); +-void EXPORT_FUNC (_restgpr_20_x) (void); +-void EXPORT_FUNC (_restgpr_21_x) (void); +-void EXPORT_FUNC (_restgpr_22_x) (void); +-void EXPORT_FUNC (_restgpr_23_x) (void); +-void EXPORT_FUNC (_restgpr_24_x) (void); +-void EXPORT_FUNC (_restgpr_25_x) (void); +-void EXPORT_FUNC (_restgpr_26_x) (void); +-void EXPORT_FUNC (_restgpr_27_x) (void); +-void EXPORT_FUNC (_restgpr_28_x) (void); +-void EXPORT_FUNC (_restgpr_29_x) (void); +-void EXPORT_FUNC (_restgpr_30_x) (void); +-void EXPORT_FUNC (_restgpr_31_x) (void); +-void EXPORT_FUNC (_savegpr_14) (void); +-void EXPORT_FUNC (_savegpr_15) (void); +-void EXPORT_FUNC (_savegpr_16) (void); +-void EXPORT_FUNC (_savegpr_17) (void); +-void EXPORT_FUNC (_savegpr_18) (void); +-void EXPORT_FUNC (_savegpr_19) (void); +-void EXPORT_FUNC (_savegpr_20) (void); +-void EXPORT_FUNC (_savegpr_21) (void); +-void EXPORT_FUNC (_savegpr_22) (void); +-void EXPORT_FUNC (_savegpr_23) (void); +-void EXPORT_FUNC (_savegpr_24) (void); +-void EXPORT_FUNC (_savegpr_25) (void); +-void EXPORT_FUNC (_savegpr_26) (void); +-void EXPORT_FUNC (_savegpr_27) (void); +-void EXPORT_FUNC (_savegpr_28) (void); +-void EXPORT_FUNC (_savegpr_29) (void); +-void EXPORT_FUNC (_savegpr_30) (void); +-void EXPORT_FUNC (_savegpr_31) (void); +-#endif +- + #if defined (__arm__) + void EXPORT_FUNC (__aeabi_lasr) (void); + void EXPORT_FUNC (__aeabi_llsl) (void); +diff --git a/grub-core/kern/powerpc/compiler-rt.S b/grub-core/kern/powerpc/compiler-rt.S +new file mode 100644 +index 00000000000..63e3a0d4e89 +--- /dev/null ++++ b/grub-core/kern/powerpc/compiler-rt.S +@@ -0,0 +1,130 @@ ++/* ++ * Special support for eabi and SVR4 ++ * ++ * Copyright (C) 1995-2014 Free Software Foundation, Inc. ++ * Written By Michael Meissner ++ * 64-bit support written by David Edelsohn ++ * ++ * This file is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 3, or (at your option) any ++ * later version. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * Under Section 7 of GPL version 3, you are granted additional ++ * permissions described in the GCC Runtime Library Exception, version ++ * 3.1, as published by the Free Software Foundation. ++ * ++ * You should have received a copy of the GNU General Public License and ++ * a copy of the GCC Runtime Library Exception along with this program; ++ * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see ++ * . ++ */ ++ ++/* Do any initializations needed for the eabi environment */ ++ ++#include ++#include ++ ++ .section ".text" ++ ++#define CFI_RESTORE(reg) .cfi_restore reg ++#define CFI_OFFSET(reg, off) .cfi_offset reg, off ++#define CFI_DEF_CFA_REGISTER(reg) .cfi_def_cfa_register reg ++#define CFI_STARTPROC .cfi_startproc ++#define CFI_ENDPROC .cfi_endproc ++ ++/* Routines for restoring integer registers, called by the compiler. */ ++/* Called with r11 pointing to the stack header word of the caller of the */ ++/* function, just beyond the end of the integer restore area. */ ++ ++CFI_STARTPROC ++CFI_DEF_CFA_REGISTER (11) ++CFI_OFFSET (65, 4) ++CFI_OFFSET (14, -72) ++CFI_OFFSET (15, -68) ++CFI_OFFSET (16, -64) ++CFI_OFFSET (17, -60) ++CFI_OFFSET (18, -56) ++CFI_OFFSET (19, -52) ++CFI_OFFSET (20, -48) ++CFI_OFFSET (21, -44) ++CFI_OFFSET (22, -40) ++CFI_OFFSET (23, -36) ++CFI_OFFSET (24, -32) ++CFI_OFFSET (25, -28) ++CFI_OFFSET (26, -24) ++CFI_OFFSET (27, -20) ++CFI_OFFSET (28, -16) ++CFI_OFFSET (29, -12) ++CFI_OFFSET (30, -8) ++CFI_OFFSET (31, -4) ++FUNCTION(_restgpr_14_x) lwz 14,-72(11) /* restore gp registers */ ++CFI_RESTORE (14) ++FUNCTION(_restgpr_15_x) lwz 15,-68(11) ++CFI_RESTORE (15) ++FUNCTION(_restgpr_16_x) lwz 16,-64(11) ++CFI_RESTORE (16) ++FUNCTION(_restgpr_17_x) lwz 17,-60(11) ++CFI_RESTORE (17) ++FUNCTION(_restgpr_18_x) lwz 18,-56(11) ++CFI_RESTORE (18) ++FUNCTION(_restgpr_19_x) lwz 19,-52(11) ++CFI_RESTORE (19) ++FUNCTION(_restgpr_20_x) lwz 20,-48(11) ++CFI_RESTORE (20) ++FUNCTION(_restgpr_21_x) lwz 21,-44(11) ++CFI_RESTORE (21) ++FUNCTION(_restgpr_22_x) lwz 22,-40(11) ++CFI_RESTORE (22) ++FUNCTION(_restgpr_23_x) lwz 23,-36(11) ++CFI_RESTORE (23) ++FUNCTION(_restgpr_24_x) lwz 24,-32(11) ++CFI_RESTORE (24) ++FUNCTION(_restgpr_25_x) lwz 25,-28(11) ++CFI_RESTORE (25) ++FUNCTION(_restgpr_26_x) lwz 26,-24(11) ++CFI_RESTORE (26) ++FUNCTION(_restgpr_27_x) lwz 27,-20(11) ++CFI_RESTORE (27) ++FUNCTION(_restgpr_28_x) lwz 28,-16(11) ++CFI_RESTORE (28) ++FUNCTION(_restgpr_29_x) lwz 29,-12(11) ++CFI_RESTORE (29) ++FUNCTION(_restgpr_30_x) lwz 30,-8(11) ++CFI_RESTORE (30) ++FUNCTION(_restgpr_31_x) lwz 0,4(11) ++ lwz 31,-4(11) ++CFI_RESTORE (31) ++ mtlr 0 ++CFI_RESTORE (65) ++ mr 1,11 ++CFI_DEF_CFA_REGISTER (1) ++ blr ++CFI_ENDPROC ++ ++CFI_STARTPROC ++FUNCTION(_savegpr_14) stw 14,-72(11) /* save gp registers */ ++FUNCTION(_savegpr_15) stw 15,-68(11) ++FUNCTION(_savegpr_16) stw 16,-64(11) ++FUNCTION(_savegpr_17) stw 17,-60(11) ++FUNCTION(_savegpr_18) stw 18,-56(11) ++FUNCTION(_savegpr_19) stw 19,-52(11) ++FUNCTION(_savegpr_20) stw 20,-48(11) ++FUNCTION(_savegpr_21) stw 21,-44(11) ++FUNCTION(_savegpr_22) stw 22,-40(11) ++FUNCTION(_savegpr_23) stw 23,-36(11) ++FUNCTION(_savegpr_24) stw 24,-32(11) ++FUNCTION(_savegpr_25) stw 25,-28(11) ++FUNCTION(_savegpr_26) stw 26,-24(11) ++FUNCTION(_savegpr_27) stw 27,-20(11) ++FUNCTION(_savegpr_28) stw 28,-16(11) ++FUNCTION(_savegpr_29) stw 29,-12(11) ++FUNCTION(_savegpr_30) stw 30,-8(11) ++FUNCTION(_savegpr_31) stw 31,-4(11) ++ blr ++CFI_ENDPROC diff --git a/SOURCES/0143-Suport-for-bi-endianess-in-elf-file.patch b/SOURCES/0143-Suport-for-bi-endianess-in-elf-file.patch new file mode 100644 index 0000000..e7089ab --- /dev/null +++ b/SOURCES/0143-Suport-for-bi-endianess-in-elf-file.patch @@ -0,0 +1,199 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paulo Flabiano Smorigo +Date: Fri, 15 Aug 2014 14:39:53 -0300 +Subject: [PATCH] Suport for bi-endianess in elf file + +* grub-core/kern/elf.c: check and switch endianess with grub_{be,le}_to + cpu functions. +* grub-core/kern/elfXX.c: Likewise. + +Also-by: Tomohiro B Berry +--- + grub-core/kern/elf.c | 60 +++++++++++++++++++++++++++++++++++++++-- + grub-core/kern/elfXX.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 131 insertions(+), 2 deletions(-) + +diff --git a/grub-core/kern/elf.c b/grub-core/kern/elf.c +index 5f99c43cc81..de9081180f0 100644 +--- a/grub-core/kern/elf.c ++++ b/grub-core/kern/elf.c +@@ -28,6 +28,11 @@ + + GRUB_MOD_LICENSE ("GPLv3+"); + ++void grub_elf32_check_endianess (grub_elf_t elf); ++void grub_elf64_check_endianess (grub_elf_t elf); ++grub_err_t grub_elf32_check_version (grub_elf_t elf); ++grub_err_t grub_elf64_check_version (grub_elf_t elf); ++ + /* Check if EHDR is a valid ELF header. */ + static grub_err_t + grub_elf_check_header (grub_elf_t elf) +@@ -38,10 +43,22 @@ grub_elf_check_header (grub_elf_t elf) + || e->e_ident[EI_MAG1] != ELFMAG1 + || e->e_ident[EI_MAG2] != ELFMAG2 + || e->e_ident[EI_MAG3] != ELFMAG3 +- || e->e_ident[EI_VERSION] != EV_CURRENT +- || e->e_version != EV_CURRENT) ++ || e->e_ident[EI_VERSION] != EV_CURRENT) + return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-independent ELF magic")); + ++ if (grub_elf_is_elf32 (elf)) ++ { ++ grub_elf32_check_endianess (elf); ++ grub_elf32_check_version (elf); ++ } ++ else if (grub_elf_is_elf64 (elf)) ++ { ++ grub_elf64_check_endianess (elf); ++ grub_elf64_check_version (elf); ++ } ++ else ++ return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic")); ++ + return GRUB_ERR_NONE; + } + +@@ -127,7 +144,20 @@ grub_elf_open (const char *name) + #define grub_elf_is_elfXX grub_elf_is_elf32 + #define grub_elfXX_load_phdrs grub_elf32_load_phdrs + #define ElfXX_Phdr Elf32_Phdr ++#define ElfXX_Ehdr Elf32_Ehdr + #define grub_uintXX_t grub_uint32_t ++#define grub_be_to_halfXX grub_be_to_cpu16 ++#define grub_be_to_wordXX grub_be_to_cpu32 ++#define grub_be_to_addrXX grub_be_to_cpu32 ++#define grub_be_to_offXX grub_be_to_cpu32 ++#define grub_be_to_XwordXX grub_be_to_wordXX ++#define grub_le_to_halfXX grub_le_to_cpu16 ++#define grub_le_to_wordXX grub_le_to_cpu32 ++#define grub_le_to_addrXX grub_le_to_cpu32 ++#define grub_le_to_offXX grub_le_to_cpu32 ++#define grub_le_to_XwordXX grub_le_to_wordXX ++#define grub_elfXX_check_endianess grub_elf32_check_endianess ++#define grub_elfXX_check_version grub_elf32_check_version + + #include "elfXX.c" + +@@ -140,7 +170,20 @@ grub_elf_open (const char *name) + #undef grub_elf_is_elfXX + #undef grub_elfXX_load_phdrs + #undef ElfXX_Phdr ++#undef ElfXX_Ehdr + #undef grub_uintXX_t ++#undef grub_be_to_halfXX ++#undef grub_be_to_wordXX ++#undef grub_be_to_addrXX ++#undef grub_be_to_offXX ++#undef grub_be_to_XwordXX ++#undef grub_le_to_halfXX ++#undef grub_le_to_wordXX ++#undef grub_le_to_addrXX ++#undef grub_le_to_offXX ++#undef grub_le_to_XwordXX ++#undef grub_elfXX_check_endianess ++#undef grub_elfXX_check_version + + + /* 64-bit */ +@@ -153,6 +196,19 @@ grub_elf_open (const char *name) + #define grub_elf_is_elfXX grub_elf_is_elf64 + #define grub_elfXX_load_phdrs grub_elf64_load_phdrs + #define ElfXX_Phdr Elf64_Phdr ++#define ElfXX_Ehdr Elf64_Ehdr + #define grub_uintXX_t grub_uint64_t ++#define grub_be_to_halfXX grub_be_to_cpu16 ++#define grub_be_to_wordXX grub_be_to_cpu32 ++#define grub_be_to_addrXX grub_be_to_cpu64 ++#define grub_be_to_offXX grub_be_to_cpu64 ++#define grub_be_to_XwordXX grub_be_to_cpu64 ++#define grub_le_to_halfXX grub_le_to_cpu16 ++#define grub_le_to_wordXX grub_le_to_cpu32 ++#define grub_le_to_addrXX grub_le_to_cpu64 ++#define grub_le_to_offXX grub_le_to_cpu64 ++#define grub_le_to_XwordXX grub_le_to_cpu64 ++#define grub_elfXX_check_endianess grub_elf64_check_endianess ++#define grub_elfXX_check_version grub_elf64_check_version + + #include "elfXX.c" +diff --git a/grub-core/kern/elfXX.c b/grub-core/kern/elfXX.c +index 1d0997186f7..ecf9df63a5e 100644 +--- a/grub-core/kern/elfXX.c ++++ b/grub-core/kern/elfXX.c +@@ -154,3 +154,76 @@ grub_elfXX_load (grub_elf_t elf, const char *filename, + + return grub_errno; + } ++ ++void ++grub_elfXX_check_endianess (grub_elf_t elf) ++{ ++ ElfXX_Ehdr *e = &(elf->ehdr.ehdrXX); ++ ElfXX_Phdr *phdr; ++ ++ if (e->e_ident[EI_DATA] == ELFDATA2MSB) ++ { ++ e->e_type = grub_be_to_halfXX (e->e_type); ++ e->e_machine = grub_be_to_halfXX (e->e_machine); ++ e->e_version = grub_be_to_wordXX (e->e_version); ++ e->e_entry = grub_be_to_addrXX (e->e_entry); ++ e->e_phoff = grub_be_to_offXX (e->e_phoff); ++ e->e_shoff = grub_be_to_offXX (e->e_shoff); ++ e->e_flags = grub_be_to_wordXX (e->e_flags); ++ e->e_ehsize = grub_be_to_halfXX (e->e_ehsize); ++ e->e_phentsize = grub_be_to_halfXX (e->e_phentsize); ++ e->e_phnum = grub_be_to_halfXX (e->e_phnum); ++ e->e_shentsize = grub_be_to_halfXX (e->e_shentsize); ++ e->e_shnum = grub_be_to_halfXX (e->e_shnum); ++ e->e_shstrndx = grub_be_to_halfXX (e->e_shstrndx); ++ ++ FOR_ELFXX_PHDRS (elf,phdr) ++ { ++ phdr->p_type = grub_be_to_wordXX (phdr->p_type); ++ phdr->p_flags = grub_be_to_wordXX (phdr->p_flags); ++ phdr->p_offset = grub_be_to_offXX (phdr->p_offset); ++ phdr->p_vaddr = grub_be_to_addrXX (phdr->p_vaddr); ++ phdr->p_paddr = grub_be_to_addrXX (phdr->p_paddr); ++ phdr->p_filesz = grub_be_to_XwordXX (phdr->p_filesz); ++ phdr->p_memsz = grub_be_to_XwordXX (phdr->p_memsz); ++ phdr->p_align = grub_be_to_XwordXX (phdr->p_align); ++ } ++ } ++ else if (e->e_ident[EI_DATA] == ELFDATA2LSB) ++ { ++ e->e_type = grub_le_to_halfXX (e->e_type); ++ e->e_machine = grub_le_to_halfXX (e->e_machine); ++ e->e_version = grub_le_to_wordXX (e->e_version); ++ e->e_entry = grub_le_to_addrXX (e->e_entry); ++ e->e_phoff = grub_le_to_offXX (e->e_phoff); ++ e->e_shoff = grub_le_to_offXX (e->e_shoff); ++ e->e_flags = grub_le_to_wordXX (e->e_flags); ++ e->e_ehsize = grub_le_to_halfXX (e->e_ehsize); ++ e->e_phentsize = grub_le_to_halfXX (e->e_phentsize); ++ e->e_phnum = grub_le_to_halfXX (e->e_phnum); ++ e->e_shentsize = grub_le_to_halfXX (e->e_shentsize); ++ e->e_shnum = grub_le_to_halfXX (e->e_shnum); ++ e->e_shstrndx = grub_le_to_halfXX (e->e_shstrndx); ++ ++ FOR_ELFXX_PHDRS (elf,phdr) ++ { ++ phdr->p_type = grub_le_to_wordXX (phdr->p_type); ++ phdr->p_flags = grub_le_to_wordXX (phdr->p_flags); ++ phdr->p_offset = grub_le_to_offXX (phdr->p_offset); ++ phdr->p_vaddr = grub_le_to_addrXX (phdr->p_vaddr); ++ phdr->p_paddr = grub_le_to_addrXX (phdr->p_paddr); ++ phdr->p_filesz = grub_le_to_XwordXX (phdr->p_filesz); ++ phdr->p_memsz = grub_le_to_XwordXX (phdr->p_memsz); ++ phdr->p_align = grub_le_to_XwordXX (phdr->p_align); ++ } ++ } ++} ++ ++grub_err_t ++grub_elfXX_check_version (grub_elf_t elf) ++{ ++ if (elf->ehdr.ehdrXX.e_version != EV_CURRENT) ++ return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-independent ELF magic")); ++ ++ return GRUB_ERR_NONE; ++} diff --git a/SOURCES/0144-Fix-exit-back-to-EFI-firmware.patch b/SOURCES/0144-Fix-exit-back-to-EFI-firmware.patch new file mode 100644 index 0000000..5478dd2 --- /dev/null +++ b/SOURCES/0144-Fix-exit-back-to-EFI-firmware.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Fedora Ninjas +Date: Fri, 15 Aug 2014 11:29:22 -0400 +Subject: [PATCH] Fix exit back to EFI firmware + +Arm/AArch64 machines set up a timer event which is not getting +canceled when returning to firmware. This is because grub_exit() +calls grub_efi_fini() instead of grub_machine_fini(). The latter +will shutdown the timer (and other machine-specific things) as +well as make the call to grub_efi_fini(). +--- + grub-core/kern/arm/efi/init.c | 2 +- + grub-core/kern/efi/efi.c | 3 ++- + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/grub-core/kern/arm/efi/init.c b/grub-core/kern/arm/efi/init.c +index 0c17d8390fa..06df60e2f0e 100644 +--- a/grub-core/kern/arm/efi/init.c ++++ b/grub-core/kern/arm/efi/init.c +@@ -67,7 +67,7 @@ grub_machine_fini (int flags) + + b = grub_efi_system_table->boot_services; + +- efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_PERIODIC, 0); ++ efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_CANCEL, 0); + efi_call_1 (b->close_event, tmr_evt); + + grub_efi_fini (); +diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c +index 1a8dba531b6..d99a6fbdf0d 100644 +--- a/grub-core/kern/efi/efi.c ++++ b/grub-core/kern/efi/efi.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + /* The handle of GRUB itself. Filled in by the startup code. */ + grub_efi_handle_t grub_efi_image_handle; +@@ -156,7 +157,7 @@ grub_efi_get_loaded_image (grub_efi_handle_t image_handle) + void + grub_exit (void) + { +- grub_efi_fini (); ++ grub_machine_fini (GRUB_LOADER_FLAG_NORETURN); + efi_call_4 (grub_efi_system_table->boot_services->exit, + grub_efi_image_handle, GRUB_EFI_LOAD_ERROR, 0, 0); + for (;;) ; diff --git a/SOURCES/0145-Add-grub_util_readlink.patch b/SOURCES/0145-Add-grub_util_readlink.patch new file mode 100644 index 0000000..122f799 --- /dev/null +++ b/SOURCES/0145-Add-grub_util_readlink.patch @@ -0,0 +1,3731 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 3 Sep 2014 10:01:03 -0400 +Subject: [PATCH] Add grub_util_readlink() + +Add grub_util_readlink(). This requires pulling in stat and readlink from +gnulib, which pulls in stat and related headers, but after that the +implementation is straightforward. + +Signed-off-by: Peter Jones +Reviewed-by: Adam Jackson +--- + grub-core/gnulib/gettimeofday.c | 154 +++++++ + grub-core/gnulib/readlink.c | 74 ++++ + grub-core/gnulib/stat.c | 138 +++++++ + grub-core/osdep/windows/hostdisk.c | 6 + + grub-core/gnulib/pathmax.h | 83 ++++ + grub-core/gnulib/sys_stat.in.h | 732 ++++++++++++++++++++++++++++++++++ + grub-core/gnulib/sys_time.in.h | 213 ++++++++++ + grub-core/gnulib/sys_types.in.h | 2 + + grub-core/gnulib/time.h | 586 +++++++++++++++++++++++++++ + grub-core/gnulib/time.in.h | 274 +++++++++++++ + include/grub/osdep/hostfile_aros.h | 6 + + include/grub/osdep/hostfile_unix.h | 6 + + include/grub/osdep/hostfile_windows.h | 2 + + grub-core/gnulib/Makefile.am | 177 +++++++- + m4/gettimeofday.m4 | 138 +++++++ + m4/gnulib-cache.m4 | 3 +- + m4/gnulib-comp.m4 | 49 +++ + m4/largefile.m4 | 146 +++++++ + m4/pathmax.m4 | 42 ++ + m4/readlink.m4 | 71 ++++ + m4/stat.m4 | 71 ++++ + m4/sys_stat_h.m4 | 96 +++++ + m4/sys_time_h.m4 | 110 +++++ + m4/time_h.m4 | 118 ++++++ + 24 files changed, 3295 insertions(+), 2 deletions(-) + create mode 100644 grub-core/gnulib/gettimeofday.c + create mode 100644 grub-core/gnulib/readlink.c + create mode 100644 grub-core/gnulib/stat.c + create mode 100644 grub-core/gnulib/pathmax.h + create mode 100644 grub-core/gnulib/sys_stat.in.h + create mode 100644 grub-core/gnulib/sys_time.in.h + create mode 100644 grub-core/gnulib/time.h + create mode 100644 grub-core/gnulib/time.in.h + create mode 100644 m4/gettimeofday.m4 + create mode 100644 m4/largefile.m4 + create mode 100644 m4/pathmax.m4 + create mode 100644 m4/readlink.m4 + create mode 100644 m4/stat.m4 + create mode 100644 m4/sys_stat_h.m4 + create mode 100644 m4/sys_time_h.m4 + create mode 100644 m4/time_h.m4 + +diff --git a/grub-core/gnulib/gettimeofday.c b/grub-core/gnulib/gettimeofday.c +new file mode 100644 +index 00000000000..8b2058e8c87 +--- /dev/null ++++ b/grub-core/gnulib/gettimeofday.c +@@ -0,0 +1,154 @@ ++/* Provide gettimeofday for systems that don't have it or for which it's broken. ++ ++ Copyright (C) 2001-2003, 2005-2007, 2009-2014 Free Software Foundation, Inc. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3, or (at your option) ++ any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, see . */ ++ ++/* written by Jim Meyering */ ++ ++#include ++ ++/* Specification. */ ++#include ++ ++#include ++ ++#if HAVE_SYS_TIMEB_H ++# include ++#endif ++ ++#if GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME ++ ++/* Work around the bug in some systems whereby gettimeofday clobbers ++ the static buffer that localtime uses for its return value. The ++ gettimeofday function from Mac OS X 10.0.4 (i.e., Darwin 1.3.7) has ++ this problem. The tzset replacement is necessary for at least ++ Solaris 2.5, 2.5.1, and 2.6. */ ++ ++static struct tm tm_zero_buffer; ++static struct tm *localtime_buffer_addr = &tm_zero_buffer; ++ ++# undef localtime ++extern struct tm *localtime (time_t const *); ++ ++# undef gmtime ++extern struct tm *gmtime (time_t const *); ++ ++/* This is a wrapper for localtime. It is used only on systems for which ++ gettimeofday clobbers the static buffer used for localtime's result. ++ ++ On the first call, record the address of the static buffer that ++ localtime uses for its result. */ ++ ++struct tm * ++rpl_localtime (time_t const *timep) ++{ ++ struct tm *tm = localtime (timep); ++ ++ if (localtime_buffer_addr == &tm_zero_buffer) ++ localtime_buffer_addr = tm; ++ ++ return tm; ++} ++ ++/* Same as above, since gmtime and localtime use the same buffer. */ ++struct tm * ++rpl_gmtime (time_t const *timep) ++{ ++ struct tm *tm = gmtime (timep); ++ ++ if (localtime_buffer_addr == &tm_zero_buffer) ++ localtime_buffer_addr = tm; ++ ++ return tm; ++} ++ ++#endif /* GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME */ ++ ++#if TZSET_CLOBBERS_LOCALTIME ++ ++# undef tzset ++extern void tzset (void); ++ ++/* This is a wrapper for tzset, for systems on which tzset may clobber ++ the static buffer used for localtime's result. */ ++void ++rpl_tzset (void) ++{ ++ /* Save and restore the contents of the buffer used for localtime's ++ result around the call to tzset. */ ++ struct tm save = *localtime_buffer_addr; ++ tzset (); ++ *localtime_buffer_addr = save; ++} ++#endif ++ ++/* This is a wrapper for gettimeofday. It is used only on systems ++ that lack this function, or whose implementation of this function ++ causes problems. */ ++ ++int ++gettimeofday (struct timeval *restrict tv, void *restrict tz) ++{ ++#undef gettimeofday ++#if HAVE_GETTIMEOFDAY ++# if GETTIMEOFDAY_CLOBBERS_LOCALTIME ++ /* Save and restore the contents of the buffer used for localtime's ++ result around the call to gettimeofday. */ ++ struct tm save = *localtime_buffer_addr; ++# endif ++ ++# if defined timeval /* 'struct timeval' overridden by gnulib? */ ++# undef timeval ++ struct timeval otv; ++ int result = gettimeofday (&otv, (struct timezone *) tz); ++ if (result == 0) ++ { ++ tv->tv_sec = otv.tv_sec; ++ tv->tv_usec = otv.tv_usec; ++ } ++# else ++ int result = gettimeofday (tv, (struct timezone *) tz); ++# endif ++ ++# if GETTIMEOFDAY_CLOBBERS_LOCALTIME ++ *localtime_buffer_addr = save; ++# endif ++ ++ return result; ++ ++#else ++ ++# if HAVE__FTIME ++ ++ struct _timeb timebuf; ++ _ftime (&timebuf); ++ tv->tv_sec = timebuf.time; ++ tv->tv_usec = timebuf.millitm * 1000; ++ ++# else ++ ++# if !defined OK_TO_USE_1S_CLOCK ++# error "Only 1-second nominal clock resolution found. Is that intended?" \ ++ "If so, compile with the -DOK_TO_USE_1S_CLOCK option." ++# endif ++ tv->tv_sec = time (NULL); ++ tv->tv_usec = 0; ++ ++# endif ++ ++ return 0; ++ ++#endif ++} +diff --git a/grub-core/gnulib/readlink.c b/grub-core/gnulib/readlink.c +new file mode 100644 +index 00000000000..4c496395176 +--- /dev/null ++++ b/grub-core/gnulib/readlink.c +@@ -0,0 +1,74 @@ ++/* Stub for readlink(). ++ Copyright (C) 2003-2007, 2009-2014 Free Software Foundation, Inc. ++ ++ This program is free software: you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . */ ++ ++#include ++ ++/* Specification. */ ++#include ++ ++#include ++#include ++#include ++ ++#if !HAVE_READLINK ++ ++/* readlink() substitute for systems that don't have a readlink() function, ++ such as DJGPP 2.03 and mingw32. */ ++ ++ssize_t ++readlink (const char *name, char *buf _GL_UNUSED, ++ size_t bufsize _GL_UNUSED) ++{ ++ struct stat statbuf; ++ ++ /* In general we should use lstat() here, not stat(). But on platforms ++ without symbolic links, lstat() - if it exists - would be equivalent to ++ stat(), therefore we can use stat(). This saves us a configure check. */ ++ if (stat (name, &statbuf) >= 0) ++ errno = EINVAL; ++ return -1; ++} ++ ++#else /* HAVE_READLINK */ ++ ++# undef readlink ++ ++/* readlink() wrapper that uses correct types, for systems like cygwin ++ 1.5.x where readlink returns int, and which rejects trailing slash, ++ for Solaris 9. */ ++ ++ssize_t ++rpl_readlink (const char *name, char *buf, size_t bufsize) ++{ ++# if READLINK_TRAILING_SLASH_BUG ++ size_t len = strlen (name); ++ if (len && name[len - 1] == '/') ++ { ++ /* Even if name without the slash is a symlink to a directory, ++ both lstat() and stat() must resolve the trailing slash to ++ the directory rather than the symlink. We can therefore ++ safely use stat() to distinguish between EINVAL and ++ ENOTDIR/ENOENT, avoiding extra overhead of rpl_lstat(). */ ++ struct stat st; ++ if (stat (name, &st) == 0) ++ errno = EINVAL; ++ return -1; ++ } ++# endif /* READLINK_TRAILING_SLASH_BUG */ ++ return readlink (name, buf, bufsize); ++} ++ ++#endif /* HAVE_READLINK */ +diff --git a/grub-core/gnulib/stat.c b/grub-core/gnulib/stat.c +new file mode 100644 +index 00000000000..35f4b0b1a51 +--- /dev/null ++++ b/grub-core/gnulib/stat.c +@@ -0,0 +1,138 @@ ++/* Work around platform bugs in stat. ++ Copyright (C) 2009-2014 Free Software Foundation, Inc. ++ ++ This program is free software: you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . */ ++ ++/* written by Eric Blake */ ++ ++/* If the user's config.h happens to include , let it include only ++ the system's here, so that orig_stat doesn't recurse to ++ rpl_stat. */ ++#define __need_system_sys_stat_h ++#include ++ ++/* Get the original definition of stat. It might be defined as a macro. */ ++#include ++#include ++#undef __need_system_sys_stat_h ++ ++#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ ++# if _GL_WINDOWS_64_BIT_ST_SIZE ++# undef stat /* avoid warning on mingw64 with _FILE_OFFSET_BITS=64 */ ++# define stat _stati64 ++# define REPLACE_FUNC_STAT_DIR 1 ++# undef REPLACE_FUNC_STAT_FILE ++# elif REPLACE_FUNC_STAT_FILE ++/* mingw64 has a broken stat() function, based on _stat(), in libmingwex.a. ++ Bypass it. */ ++# define stat _stat ++# define REPLACE_FUNC_STAT_DIR 1 ++# undef REPLACE_FUNC_STAT_FILE ++# endif ++#endif ++ ++static int ++orig_stat (const char *filename, struct stat *buf) ++{ ++ return stat (filename, buf); ++} ++ ++/* Specification. */ ++/* Write "sys/stat.h" here, not , otherwise OSF/1 5.1 DTK cc ++ eliminates this include because of the preliminary #include ++ above. */ ++#include "sys/stat.h" ++ ++#include ++#include ++#include ++#include ++#include "dosname.h" ++#include "verify.h" ++ ++#if REPLACE_FUNC_STAT_DIR ++# include "pathmax.h" ++ /* The only known systems where REPLACE_FUNC_STAT_DIR is needed also ++ have a constant PATH_MAX. */ ++# ifndef PATH_MAX ++# error "Please port this replacement to your platform" ++# endif ++#endif ++ ++/* Store information about NAME into ST. Work around bugs with ++ trailing slashes. Mingw has other bugs (such as st_ino always ++ being 0 on success) which this wrapper does not work around. But ++ at least this implementation provides the ability to emulate fchdir ++ correctly. */ ++ ++int ++rpl_stat (char const *name, struct stat *st) ++{ ++ int result = orig_stat (name, st); ++#if REPLACE_FUNC_STAT_FILE ++ /* Solaris 9 mistakenly succeeds when given a non-directory with a ++ trailing slash. */ ++ if (result == 0 && !S_ISDIR (st->st_mode)) ++ { ++ size_t len = strlen (name); ++ if (ISSLASH (name[len - 1])) ++ { ++ errno = ENOTDIR; ++ return -1; ++ } ++ } ++#endif /* REPLACE_FUNC_STAT_FILE */ ++#if REPLACE_FUNC_STAT_DIR ++ ++ if (result == -1 && errno == ENOENT) ++ { ++ /* Due to mingw's oddities, there are some directories (like ++ c:\) where stat() only succeeds with a trailing slash, and ++ other directories (like c:\windows) where stat() only ++ succeeds without a trailing slash. But we want the two to be ++ synonymous, since chdir() manages either style. Likewise, Mingw also ++ reports ENOENT for names longer than PATH_MAX, when we want ++ ENAMETOOLONG, and for stat("file/"), when we want ENOTDIR. ++ Fortunately, mingw PATH_MAX is small enough for stack ++ allocation. */ ++ char fixed_name[PATH_MAX + 1] = {0}; ++ size_t len = strlen (name); ++ bool check_dir = false; ++ verify (PATH_MAX <= 4096); ++ if (PATH_MAX <= len) ++ errno = ENAMETOOLONG; ++ else if (len) ++ { ++ strcpy (fixed_name, name); ++ if (ISSLASH (fixed_name[len - 1])) ++ { ++ check_dir = true; ++ while (len && ISSLASH (fixed_name[len - 1])) ++ fixed_name[--len] = '\0'; ++ if (!len) ++ fixed_name[0] = '/'; ++ } ++ else ++ fixed_name[len++] = '/'; ++ result = orig_stat (fixed_name, st); ++ if (result == 0 && check_dir && !S_ISDIR (st->st_mode)) ++ { ++ result = -1; ++ errno = ENOTDIR; ++ } ++ } ++ } ++#endif /* REPLACE_FUNC_STAT_DIR */ ++ return result; ++} +diff --git a/grub-core/osdep/windows/hostdisk.c b/grub-core/osdep/windows/hostdisk.c +index d390b25fcbe..9127e9263b1 100644 +--- a/grub-core/osdep/windows/hostdisk.c ++++ b/grub-core/osdep/windows/hostdisk.c +@@ -353,6 +353,12 @@ grub_util_mkdir (const char *dir) + free (windows_name); + } + ++ssize_t ++grub_util_readlink (const char *name, char *buf, size_t bufsize) ++{ ++ return readlink(name, buf, bufsize); ++} ++ + int + grub_util_rename (const char *from, const char *to) + { +diff --git a/grub-core/gnulib/pathmax.h b/grub-core/gnulib/pathmax.h +new file mode 100644 +index 00000000000..33fc3553d75 +--- /dev/null ++++ b/grub-core/gnulib/pathmax.h +@@ -0,0 +1,83 @@ ++/* Define PATH_MAX somehow. Requires sys/types.h. ++ Copyright (C) 1992, 1999, 2001, 2003, 2005, 2009-2014 Free Software ++ Foundation, Inc. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3, or (at your option) ++ any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, see . */ ++ ++#ifndef _PATHMAX_H ++# define _PATHMAX_H ++ ++/* POSIX:2008 defines PATH_MAX to be the maximum number of bytes in a filename, ++ including the terminating NUL byte. ++ ++ PATH_MAX is not defined on systems which have no limit on filename length, ++ such as GNU/Hurd. ++ ++ This file does *not* define PATH_MAX always. Programs that use this file ++ can handle the GNU/Hurd case in several ways: ++ - Either with a package-wide handling, or with a per-file handling, ++ - Either through a ++ #ifdef PATH_MAX ++ or through a fallback like ++ #ifndef PATH_MAX ++ # define PATH_MAX 8192 ++ #endif ++ or through a fallback like ++ #ifndef PATH_MAX ++ # define PATH_MAX pathconf ("/", _PC_PATH_MAX) ++ #endif ++ */ ++ ++# include ++ ++# include ++ ++# ifndef _POSIX_PATH_MAX ++# define _POSIX_PATH_MAX 256 ++# endif ++ ++/* Don't include sys/param.h if it already has been. */ ++# if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN ++# include ++# endif ++ ++# if !defined PATH_MAX && defined MAXPATHLEN ++# define PATH_MAX MAXPATHLEN ++# endif ++ ++# ifdef __hpux ++/* On HP-UX, PATH_MAX designates the maximum number of bytes in a filename, ++ *not* including the terminating NUL byte, and is set to 1023. ++ Additionally, when _XOPEN_SOURCE is defined to 500 or more, PATH_MAX is ++ not defined at all any more. */ ++# undef PATH_MAX ++# define PATH_MAX 1024 ++# endif ++ ++# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ ++/* The page "Naming Files, Paths, and Namespaces" on msdn.microsoft.com, ++ section "Maximum Path Length Limitation", ++ ++ explains that the maximum size of a filename, including the terminating ++ NUL byte, is 260 = 3 + 256 + 1. ++ This is the same value as ++ - FILENAME_MAX in , ++ - _MAX_PATH in , ++ - MAX_PATH in . ++ Undefine the original value, because mingw's gets it wrong. */ ++# undef PATH_MAX ++# define PATH_MAX 260 ++# endif ++ ++#endif /* _PATHMAX_H */ +diff --git a/grub-core/gnulib/sys_stat.in.h b/grub-core/gnulib/sys_stat.in.h +new file mode 100644 +index 00000000000..b47a7ff0ae7 +--- /dev/null ++++ b/grub-core/gnulib/sys_stat.in.h +@@ -0,0 +1,732 @@ ++/* Provide a more complete sys/stat header file. ++ Copyright (C) 2005-2014 Free Software Foundation, Inc. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3, or (at your option) ++ any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, see . */ ++ ++/* Written by Eric Blake, Paul Eggert, and Jim Meyering. */ ++ ++/* This file is supposed to be used on platforms where is ++ incomplete. It is intended to provide definitions and prototypes ++ needed by an application. Start with what the system provides. */ ++ ++#if __GNUC__ >= 3 ++@PRAGMA_SYSTEM_HEADER@ ++#endif ++@PRAGMA_COLUMNS@ ++ ++#if defined __need_system_sys_stat_h ++/* Special invocation convention. */ ++ ++#@INCLUDE_NEXT@ @NEXT_SYS_STAT_H@ ++ ++#else ++/* Normal invocation convention. */ ++ ++#ifndef _@GUARD_PREFIX@_SYS_STAT_H ++ ++/* Get nlink_t. ++ May also define off_t to a 64-bit type on native Windows. */ ++#include ++ ++/* Get struct timespec. */ ++#include ++ ++/* The include_next requires a split double-inclusion guard. */ ++#@INCLUDE_NEXT@ @NEXT_SYS_STAT_H@ ++ ++#ifndef _@GUARD_PREFIX@_SYS_STAT_H ++#define _@GUARD_PREFIX@_SYS_STAT_H ++ ++/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ ++ ++/* The definition of _GL_ARG_NONNULL is copied here. */ ++ ++/* The definition of _GL_WARN_ON_USE is copied here. */ ++ ++/* Before doing "#define mkdir rpl_mkdir" below, we need to include all ++ headers that may declare mkdir(). Native Windows platforms declare mkdir ++ in and/or , not in . */ ++#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ ++# include /* mingw32, mingw64 */ ++# include /* mingw64, MSVC 9 */ ++#endif ++ ++/* Native Windows platforms declare umask() in . */ ++#if 0 && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) ++# include ++#endif ++ ++/* Large File Support on native Windows. */ ++#if @WINDOWS_64_BIT_ST_SIZE@ ++# define stat _stati64 ++#endif ++ ++#ifndef S_IFIFO ++# ifdef _S_IFIFO ++# define S_IFIFO _S_IFIFO ++# endif ++#endif ++ ++#ifndef S_IFMT ++# define S_IFMT 0170000 ++#endif ++ ++#if STAT_MACROS_BROKEN ++# undef S_ISBLK ++# undef S_ISCHR ++# undef S_ISDIR ++# undef S_ISFIFO ++# undef S_ISLNK ++# undef S_ISNAM ++# undef S_ISMPB ++# undef S_ISMPC ++# undef S_ISNWK ++# undef S_ISREG ++# undef S_ISSOCK ++#endif ++ ++#ifndef S_ISBLK ++# ifdef S_IFBLK ++# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) ++# else ++# define S_ISBLK(m) 0 ++# endif ++#endif ++ ++#ifndef S_ISCHR ++# ifdef S_IFCHR ++# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) ++# else ++# define S_ISCHR(m) 0 ++# endif ++#endif ++ ++#ifndef S_ISDIR ++# ifdef S_IFDIR ++# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) ++# else ++# define S_ISDIR(m) 0 ++# endif ++#endif ++ ++#ifndef S_ISDOOR /* Solaris 2.5 and up */ ++# define S_ISDOOR(m) 0 ++#endif ++ ++#ifndef S_ISFIFO ++# ifdef S_IFIFO ++# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) ++# else ++# define S_ISFIFO(m) 0 ++# endif ++#endif ++ ++#ifndef S_ISLNK ++# ifdef S_IFLNK ++# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) ++# else ++# define S_ISLNK(m) 0 ++# endif ++#endif ++ ++#ifndef S_ISMPB /* V7 */ ++# ifdef S_IFMPB ++# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB) ++# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC) ++# else ++# define S_ISMPB(m) 0 ++# define S_ISMPC(m) 0 ++# endif ++#endif ++ ++#ifndef S_ISMPX /* AIX */ ++# define S_ISMPX(m) 0 ++#endif ++ ++#ifndef S_ISNAM /* Xenix */ ++# ifdef S_IFNAM ++# define S_ISNAM(m) (((m) & S_IFMT) == S_IFNAM) ++# else ++# define S_ISNAM(m) 0 ++# endif ++#endif ++ ++#ifndef S_ISNWK /* HP/UX */ ++# ifdef S_IFNWK ++# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK) ++# else ++# define S_ISNWK(m) 0 ++# endif ++#endif ++ ++#ifndef S_ISPORT /* Solaris 10 and up */ ++# define S_ISPORT(m) 0 ++#endif ++ ++#ifndef S_ISREG ++# ifdef S_IFREG ++# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) ++# else ++# define S_ISREG(m) 0 ++# endif ++#endif ++ ++#ifndef S_ISSOCK ++# ifdef S_IFSOCK ++# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) ++# else ++# define S_ISSOCK(m) 0 ++# endif ++#endif ++ ++ ++#ifndef S_TYPEISMQ ++# define S_TYPEISMQ(p) 0 ++#endif ++ ++#ifndef S_TYPEISTMO ++# define S_TYPEISTMO(p) 0 ++#endif ++ ++ ++#ifndef S_TYPEISSEM ++# ifdef S_INSEM ++# define S_TYPEISSEM(p) (S_ISNAM ((p)->st_mode) && (p)->st_rdev == S_INSEM) ++# else ++# define S_TYPEISSEM(p) 0 ++# endif ++#endif ++ ++#ifndef S_TYPEISSHM ++# ifdef S_INSHD ++# define S_TYPEISSHM(p) (S_ISNAM ((p)->st_mode) && (p)->st_rdev == S_INSHD) ++# else ++# define S_TYPEISSHM(p) 0 ++# endif ++#endif ++ ++/* high performance ("contiguous data") */ ++#ifndef S_ISCTG ++# define S_ISCTG(p) 0 ++#endif ++ ++/* Cray DMF (data migration facility): off line, with data */ ++#ifndef S_ISOFD ++# define S_ISOFD(p) 0 ++#endif ++ ++/* Cray DMF (data migration facility): off line, with no data */ ++#ifndef S_ISOFL ++# define S_ISOFL(p) 0 ++#endif ++ ++/* 4.4BSD whiteout */ ++#ifndef S_ISWHT ++# define S_ISWHT(m) 0 ++#endif ++ ++/* If any of the following are undefined, ++ define them to their de facto standard values. */ ++#if !S_ISUID ++# define S_ISUID 04000 ++#endif ++#if !S_ISGID ++# define S_ISGID 02000 ++#endif ++ ++/* S_ISVTX is a common extension to POSIX. */ ++#ifndef S_ISVTX ++# define S_ISVTX 01000 ++#endif ++ ++#if !S_IRUSR && S_IREAD ++# define S_IRUSR S_IREAD ++#endif ++#if !S_IRUSR ++# define S_IRUSR 00400 ++#endif ++#if !S_IRGRP ++# define S_IRGRP (S_IRUSR >> 3) ++#endif ++#if !S_IROTH ++# define S_IROTH (S_IRUSR >> 6) ++#endif ++ ++#if !S_IWUSR && S_IWRITE ++# define S_IWUSR S_IWRITE ++#endif ++#if !S_IWUSR ++# define S_IWUSR 00200 ++#endif ++#if !S_IWGRP ++# define S_IWGRP (S_IWUSR >> 3) ++#endif ++#if !S_IWOTH ++# define S_IWOTH (S_IWUSR >> 6) ++#endif ++ ++#if !S_IXUSR && S_IEXEC ++# define S_IXUSR S_IEXEC ++#endif ++#if !S_IXUSR ++# define S_IXUSR 00100 ++#endif ++#if !S_IXGRP ++# define S_IXGRP (S_IXUSR >> 3) ++#endif ++#if !S_IXOTH ++# define S_IXOTH (S_IXUSR >> 6) ++#endif ++ ++#if !S_IRWXU ++# define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) ++#endif ++#if !S_IRWXG ++# define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) ++#endif ++#if !S_IRWXO ++# define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) ++#endif ++ ++/* S_IXUGO is a common extension to POSIX. */ ++#if !S_IXUGO ++# define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH) ++#endif ++ ++#ifndef S_IRWXUGO ++# define S_IRWXUGO (S_IRWXU | S_IRWXG | S_IRWXO) ++#endif ++ ++/* Macros for futimens and utimensat. */ ++#ifndef UTIME_NOW ++# define UTIME_NOW (-1) ++# define UTIME_OMIT (-2) ++#endif ++ ++ ++#if @GNULIB_FCHMODAT@ ++# if !@HAVE_FCHMODAT@ ++_GL_FUNCDECL_SYS (fchmodat, int, ++ (int fd, char const *file, mode_t mode, int flag) ++ _GL_ARG_NONNULL ((2))); ++# endif ++_GL_CXXALIAS_SYS (fchmodat, int, ++ (int fd, char const *file, mode_t mode, int flag)); ++_GL_CXXALIASWARN (fchmodat); ++#elif defined GNULIB_POSIXCHECK ++# undef fchmodat ++# if HAVE_RAW_DECL_FCHMODAT ++_GL_WARN_ON_USE (fchmodat, "fchmodat is not portable - " ++ "use gnulib module openat for portability"); ++# endif ++#endif ++ ++ ++#if @GNULIB_FSTAT@ ++# if @REPLACE_FSTAT@ ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# undef fstat ++# define fstat rpl_fstat ++# endif ++_GL_FUNCDECL_RPL (fstat, int, (int fd, struct stat *buf) _GL_ARG_NONNULL ((2))); ++_GL_CXXALIAS_RPL (fstat, int, (int fd, struct stat *buf)); ++# else ++_GL_CXXALIAS_SYS (fstat, int, (int fd, struct stat *buf)); ++# endif ++_GL_CXXALIASWARN (fstat); ++#elif @WINDOWS_64_BIT_ST_SIZE@ ++/* Above, we define stat to _stati64. */ ++# define fstat _fstati64 ++#elif defined GNULIB_POSIXCHECK ++# undef fstat ++# if HAVE_RAW_DECL_FSTAT ++_GL_WARN_ON_USE (fstat, "fstat has portability problems - " ++ "use gnulib module fstat for portability"); ++# endif ++#endif ++ ++ ++#if @GNULIB_FSTATAT@ ++# if @REPLACE_FSTATAT@ ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# undef fstatat ++# define fstatat rpl_fstatat ++# endif ++_GL_FUNCDECL_RPL (fstatat, int, ++ (int fd, char const *name, struct stat *st, int flags) ++ _GL_ARG_NONNULL ((2, 3))); ++_GL_CXXALIAS_RPL (fstatat, int, ++ (int fd, char const *name, struct stat *st, int flags)); ++# else ++# if !@HAVE_FSTATAT@ ++_GL_FUNCDECL_SYS (fstatat, int, ++ (int fd, char const *name, struct stat *st, int flags) ++ _GL_ARG_NONNULL ((2, 3))); ++# endif ++_GL_CXXALIAS_SYS (fstatat, int, ++ (int fd, char const *name, struct stat *st, int flags)); ++# endif ++_GL_CXXALIASWARN (fstatat); ++#elif defined GNULIB_POSIXCHECK ++# undef fstatat ++# if HAVE_RAW_DECL_FSTATAT ++_GL_WARN_ON_USE (fstatat, "fstatat is not portable - " ++ "use gnulib module openat for portability"); ++# endif ++#endif ++ ++ ++#if @GNULIB_FUTIMENS@ ++/* Use the rpl_ prefix also on Solaris <= 9, because on Solaris 9 our futimens ++ implementation relies on futimesat, which on Solaris 10 makes an invocation ++ to futimens that is meant to invoke the libc's futimens(), not gnulib's ++ futimens(). */ ++# if @REPLACE_FUTIMENS@ || (!@HAVE_FUTIMENS@ && defined __sun) ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# undef futimens ++# define futimens rpl_futimens ++# endif ++_GL_FUNCDECL_RPL (futimens, int, (int fd, struct timespec const times[2])); ++_GL_CXXALIAS_RPL (futimens, int, (int fd, struct timespec const times[2])); ++# else ++# if !@HAVE_FUTIMENS@ ++_GL_FUNCDECL_SYS (futimens, int, (int fd, struct timespec const times[2])); ++# endif ++_GL_CXXALIAS_SYS (futimens, int, (int fd, struct timespec const times[2])); ++# endif ++# if @HAVE_FUTIMENS@ ++_GL_CXXALIASWARN (futimens); ++# endif ++#elif defined GNULIB_POSIXCHECK ++# undef futimens ++# if HAVE_RAW_DECL_FUTIMENS ++_GL_WARN_ON_USE (futimens, "futimens is not portable - " ++ "use gnulib module futimens for portability"); ++# endif ++#endif ++ ++ ++#if @GNULIB_LCHMOD@ ++/* Change the mode of FILENAME to MODE, without dereferencing it if FILENAME ++ denotes a symbolic link. */ ++# if !@HAVE_LCHMOD@ ++/* The lchmod replacement follows symbolic links. Callers should take ++ this into account; lchmod should be applied only to arguments that ++ are known to not be symbolic links. On hosts that lack lchmod, ++ this can lead to race conditions between the check and the ++ invocation of lchmod, but we know of no workarounds that are ++ reliable in general. You might try requesting support for lchmod ++ from your operating system supplier. */ ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# define lchmod chmod ++# endif ++/* Need to cast, because on mingw, the second parameter of chmod is ++ int mode. */ ++_GL_CXXALIAS_RPL_CAST_1 (lchmod, chmod, int, ++ (const char *filename, mode_t mode)); ++# else ++# if 0 /* assume already declared */ ++_GL_FUNCDECL_SYS (lchmod, int, (const char *filename, mode_t mode) ++ _GL_ARG_NONNULL ((1))); ++# endif ++_GL_CXXALIAS_SYS (lchmod, int, (const char *filename, mode_t mode)); ++# endif ++# if @HAVE_LCHMOD@ ++_GL_CXXALIASWARN (lchmod); ++# endif ++#elif defined GNULIB_POSIXCHECK ++# undef lchmod ++# if HAVE_RAW_DECL_LCHMOD ++_GL_WARN_ON_USE (lchmod, "lchmod is unportable - " ++ "use gnulib module lchmod for portability"); ++# endif ++#endif ++ ++ ++#if @GNULIB_LSTAT@ ++# if ! @HAVE_LSTAT@ ++/* mingw does not support symlinks, therefore it does not have lstat. But ++ without links, stat does just fine. */ ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# define lstat stat ++# endif ++_GL_CXXALIAS_RPL_1 (lstat, stat, int, (const char *name, struct stat *buf)); ++# elif @REPLACE_LSTAT@ ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# undef lstat ++# define lstat rpl_lstat ++# endif ++_GL_FUNCDECL_RPL (lstat, int, (const char *name, struct stat *buf) ++ _GL_ARG_NONNULL ((1, 2))); ++_GL_CXXALIAS_RPL (lstat, int, (const char *name, struct stat *buf)); ++# else ++_GL_CXXALIAS_SYS (lstat, int, (const char *name, struct stat *buf)); ++# endif ++# if @HAVE_LSTAT@ ++_GL_CXXALIASWARN (lstat); ++# endif ++#elif defined GNULIB_POSIXCHECK ++# undef lstat ++# if HAVE_RAW_DECL_LSTAT ++_GL_WARN_ON_USE (lstat, "lstat is unportable - " ++ "use gnulib module lstat for portability"); ++# endif ++#endif ++ ++ ++#if @REPLACE_MKDIR@ ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# undef mkdir ++# define mkdir rpl_mkdir ++# endif ++_GL_FUNCDECL_RPL (mkdir, int, (char const *name, mode_t mode) ++ _GL_ARG_NONNULL ((1))); ++_GL_CXXALIAS_RPL (mkdir, int, (char const *name, mode_t mode)); ++#else ++/* mingw's _mkdir() function has 1 argument, but we pass 2 arguments. ++ Additionally, it declares _mkdir (and depending on compile flags, an ++ alias mkdir), only in the nonstandard includes and , ++ which are included above. */ ++# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ ++ ++# if !GNULIB_defined_rpl_mkdir ++static int ++rpl_mkdir (char const *name, mode_t mode) ++{ ++ return _mkdir (name); ++} ++# define GNULIB_defined_rpl_mkdir 1 ++# endif ++ ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# define mkdir rpl_mkdir ++# endif ++_GL_CXXALIAS_RPL (mkdir, int, (char const *name, mode_t mode)); ++# else ++_GL_CXXALIAS_SYS (mkdir, int, (char const *name, mode_t mode)); ++# endif ++#endif ++_GL_CXXALIASWARN (mkdir); ++ ++ ++#if @GNULIB_MKDIRAT@ ++# if !@HAVE_MKDIRAT@ ++_GL_FUNCDECL_SYS (mkdirat, int, (int fd, char const *file, mode_t mode) ++ _GL_ARG_NONNULL ((2))); ++# endif ++_GL_CXXALIAS_SYS (mkdirat, int, (int fd, char const *file, mode_t mode)); ++_GL_CXXALIASWARN (mkdirat); ++#elif defined GNULIB_POSIXCHECK ++# undef mkdirat ++# if HAVE_RAW_DECL_MKDIRAT ++_GL_WARN_ON_USE (mkdirat, "mkdirat is not portable - " ++ "use gnulib module openat for portability"); ++# endif ++#endif ++ ++ ++#if @GNULIB_MKFIFO@ ++# if @REPLACE_MKFIFO@ ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# undef mkfifo ++# define mkfifo rpl_mkfifo ++# endif ++_GL_FUNCDECL_RPL (mkfifo, int, (char const *file, mode_t mode) ++ _GL_ARG_NONNULL ((1))); ++_GL_CXXALIAS_RPL (mkfifo, int, (char const *file, mode_t mode)); ++# else ++# if !@HAVE_MKFIFO@ ++_GL_FUNCDECL_SYS (mkfifo, int, (char const *file, mode_t mode) ++ _GL_ARG_NONNULL ((1))); ++# endif ++_GL_CXXALIAS_SYS (mkfifo, int, (char const *file, mode_t mode)); ++# endif ++_GL_CXXALIASWARN (mkfifo); ++#elif defined GNULIB_POSIXCHECK ++# undef mkfifo ++# if HAVE_RAW_DECL_MKFIFO ++_GL_WARN_ON_USE (mkfifo, "mkfifo is not portable - " ++ "use gnulib module mkfifo for portability"); ++# endif ++#endif ++ ++ ++#if @GNULIB_MKFIFOAT@ ++# if !@HAVE_MKFIFOAT@ ++_GL_FUNCDECL_SYS (mkfifoat, int, (int fd, char const *file, mode_t mode) ++ _GL_ARG_NONNULL ((2))); ++# endif ++_GL_CXXALIAS_SYS (mkfifoat, int, (int fd, char const *file, mode_t mode)); ++_GL_CXXALIASWARN (mkfifoat); ++#elif defined GNULIB_POSIXCHECK ++# undef mkfifoat ++# if HAVE_RAW_DECL_MKFIFOAT ++_GL_WARN_ON_USE (mkfifoat, "mkfifoat is not portable - " ++ "use gnulib module mkfifoat for portability"); ++# endif ++#endif ++ ++ ++#if @GNULIB_MKNOD@ ++# if @REPLACE_MKNOD@ ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# undef mknod ++# define mknod rpl_mknod ++# endif ++_GL_FUNCDECL_RPL (mknod, int, (char const *file, mode_t mode, dev_t dev) ++ _GL_ARG_NONNULL ((1))); ++_GL_CXXALIAS_RPL (mknod, int, (char const *file, mode_t mode, dev_t dev)); ++# else ++# if !@HAVE_MKNOD@ ++_GL_FUNCDECL_SYS (mknod, int, (char const *file, mode_t mode, dev_t dev) ++ _GL_ARG_NONNULL ((1))); ++# endif ++/* Need to cast, because on OSF/1 5.1, the third parameter is '...'. */ ++_GL_CXXALIAS_SYS_CAST (mknod, int, (char const *file, mode_t mode, dev_t dev)); ++# endif ++_GL_CXXALIASWARN (mknod); ++#elif defined GNULIB_POSIXCHECK ++# undef mknod ++# if HAVE_RAW_DECL_MKNOD ++_GL_WARN_ON_USE (mknod, "mknod is not portable - " ++ "use gnulib module mknod for portability"); ++# endif ++#endif ++ ++ ++#if @GNULIB_MKNODAT@ ++# if !@HAVE_MKNODAT@ ++_GL_FUNCDECL_SYS (mknodat, int, ++ (int fd, char const *file, mode_t mode, dev_t dev) ++ _GL_ARG_NONNULL ((2))); ++# endif ++_GL_CXXALIAS_SYS (mknodat, int, ++ (int fd, char const *file, mode_t mode, dev_t dev)); ++_GL_CXXALIASWARN (mknodat); ++#elif defined GNULIB_POSIXCHECK ++# undef mknodat ++# if HAVE_RAW_DECL_MKNODAT ++_GL_WARN_ON_USE (mknodat, "mknodat is not portable - " ++ "use gnulib module mkfifoat for portability"); ++# endif ++#endif ++ ++ ++#if @GNULIB_STAT@ ++# if @REPLACE_STAT@ ++/* We can't use the object-like #define stat rpl_stat, because of ++ struct stat. This means that rpl_stat will not be used if the user ++ does (stat)(a,b). Oh well. */ ++# if defined _AIX && defined stat && defined _LARGE_FILES ++ /* With _LARGE_FILES defined, AIX (only) defines stat to stat64, ++ so we have to replace stat64() instead of stat(). */ ++# undef stat64 ++# define stat64(name, st) rpl_stat (name, st) ++# elif @WINDOWS_64_BIT_ST_SIZE@ ++ /* Above, we define stat to _stati64. */ ++# if defined __MINGW32__ && defined _stati64 ++# ifndef _USE_32BIT_TIME_T ++ /* The system headers define _stati64 to _stat64. */ ++# undef _stat64 ++# define _stat64(name, st) rpl_stat (name, st) ++# endif ++# elif defined _MSC_VER && defined _stati64 ++# ifdef _USE_32BIT_TIME_T ++ /* The system headers define _stati64 to _stat32i64. */ ++# undef _stat32i64 ++# define _stat32i64(name, st) rpl_stat (name, st) ++# else ++ /* The system headers define _stati64 to _stat64. */ ++# undef _stat64 ++# define _stat64(name, st) rpl_stat (name, st) ++# endif ++# else ++# undef _stati64 ++# define _stati64(name, st) rpl_stat (name, st) ++# endif ++# elif defined __MINGW32__ && defined stat ++# ifdef _USE_32BIT_TIME_T ++ /* The system headers define stat to _stat32i64. */ ++# undef _stat32i64 ++# define _stat32i64(name, st) rpl_stat (name, st) ++# else ++ /* The system headers define stat to _stat64. */ ++# undef _stat64 ++# define _stat64(name, st) rpl_stat (name, st) ++# endif ++# elif defined _MSC_VER && defined stat ++# ifdef _USE_32BIT_TIME_T ++ /* The system headers define stat to _stat32. */ ++# undef _stat32 ++# define _stat32(name, st) rpl_stat (name, st) ++# else ++ /* The system headers define stat to _stat64i32. */ ++# undef _stat64i32 ++# define _stat64i32(name, st) rpl_stat (name, st) ++# endif ++# else /* !(_AIX ||__MINGW32__ || _MSC_VER) */ ++# undef stat ++# define stat(name, st) rpl_stat (name, st) ++# endif /* !_LARGE_FILES */ ++_GL_EXTERN_C int stat (const char *name, struct stat *buf) ++ _GL_ARG_NONNULL ((1, 2)); ++# endif ++#elif defined GNULIB_POSIXCHECK ++# undef stat ++# if HAVE_RAW_DECL_STAT ++_GL_WARN_ON_USE (stat, "stat is unportable - " ++ "use gnulib module stat for portability"); ++# endif ++#endif ++ ++ ++#if @GNULIB_UTIMENSAT@ ++/* Use the rpl_ prefix also on Solaris <= 9, because on Solaris 9 our utimensat ++ implementation relies on futimesat, which on Solaris 10 makes an invocation ++ to utimensat that is meant to invoke the libc's utimensat(), not gnulib's ++ utimensat(). */ ++# if @REPLACE_UTIMENSAT@ || (!@HAVE_UTIMENSAT@ && defined __sun) ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# undef utimensat ++# define utimensat rpl_utimensat ++# endif ++_GL_FUNCDECL_RPL (utimensat, int, (int fd, char const *name, ++ struct timespec const times[2], int flag) ++ _GL_ARG_NONNULL ((2))); ++_GL_CXXALIAS_RPL (utimensat, int, (int fd, char const *name, ++ struct timespec const times[2], int flag)); ++# else ++# if !@HAVE_UTIMENSAT@ ++_GL_FUNCDECL_SYS (utimensat, int, (int fd, char const *name, ++ struct timespec const times[2], int flag) ++ _GL_ARG_NONNULL ((2))); ++# endif ++_GL_CXXALIAS_SYS (utimensat, int, (int fd, char const *name, ++ struct timespec const times[2], int flag)); ++# endif ++# if @HAVE_UTIMENSAT@ ++_GL_CXXALIASWARN (utimensat); ++# endif ++#elif defined GNULIB_POSIXCHECK ++# undef utimensat ++# if HAVE_RAW_DECL_UTIMENSAT ++_GL_WARN_ON_USE (utimensat, "utimensat is not portable - " ++ "use gnulib module utimensat for portability"); ++# endif ++#endif ++ ++ ++#endif /* _@GUARD_PREFIX@_SYS_STAT_H */ ++#endif /* _@GUARD_PREFIX@_SYS_STAT_H */ ++#endif +diff --git a/grub-core/gnulib/sys_time.in.h b/grub-core/gnulib/sys_time.in.h +new file mode 100644 +index 00000000000..30057ad49fd +--- /dev/null ++++ b/grub-core/gnulib/sys_time.in.h +@@ -0,0 +1,213 @@ ++/* Provide a more complete sys/time.h. ++ ++ Copyright (C) 2007-2014 Free Software Foundation, Inc. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3, or (at your option) ++ any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, see . */ ++ ++/* Written by Paul Eggert. */ ++ ++#ifndef _@GUARD_PREFIX@_SYS_TIME_H ++ ++#if __GNUC__ >= 3 ++@PRAGMA_SYSTEM_HEADER@ ++#endif ++@PRAGMA_COLUMNS@ ++ ++/* On Cygwin and on many BSDish systems, includes itself ++ recursively via . ++ Simply delegate to the system's header in this case; it is a no-op. ++ Without this extra ifdef, the C++ gettimeofday declaration below ++ would be a forward declaration in gnulib's nested . */ ++#if defined _CYGWIN_SYS_TIME_H || defined _SYS_TIME_H || defined _SYS_TIME_H_ ++# @INCLUDE_NEXT@ @NEXT_SYS_TIME_H@ ++#else ++ ++/* The include_next requires a split double-inclusion guard. */ ++#if @HAVE_SYS_TIME_H@ ++# @INCLUDE_NEXT@ @NEXT_SYS_TIME_H@ ++#endif ++ ++#ifndef _@GUARD_PREFIX@_SYS_TIME_H ++#define _@GUARD_PREFIX@_SYS_TIME_H ++ ++#if ! @HAVE_SYS_TIME_H@ ++# include ++#endif ++ ++/* On native Windows with MSVC, get the 'struct timeval' type. ++ Also, on native Windows with a 64-bit time_t, where we are overriding the ++ 'struct timeval' type, get all declarations of system functions whose ++ signature contains 'struct timeval'. */ ++#if (defined _MSC_VER || @REPLACE_STRUCT_TIMEVAL@) && @HAVE_WINSOCK2_H@ && !defined _GL_INCLUDING_WINSOCK2_H ++# define _GL_INCLUDING_WINSOCK2_H ++# include ++# undef _GL_INCLUDING_WINSOCK2_H ++#endif ++ ++/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ ++ ++/* The definition of _GL_ARG_NONNULL is copied here. */ ++ ++/* The definition of _GL_WARN_ON_USE is copied here. */ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#if !@HAVE_STRUCT_TIMEVAL@ || @REPLACE_STRUCT_TIMEVAL@ ++ ++# if @REPLACE_STRUCT_TIMEVAL@ ++# define timeval rpl_timeval ++# endif ++ ++# if !GNULIB_defined_struct_timeval ++struct timeval ++{ ++ time_t tv_sec; ++ long int tv_usec; ++}; ++# define GNULIB_defined_struct_timeval 1 ++# endif ++ ++#endif ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#if @GNULIB_GETTIMEOFDAY@ ++# if @REPLACE_GETTIMEOFDAY@ ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# undef gettimeofday ++# define gettimeofday rpl_gettimeofday ++# endif ++_GL_FUNCDECL_RPL (gettimeofday, int, ++ (struct timeval *restrict, void *restrict) ++ _GL_ARG_NONNULL ((1))); ++_GL_CXXALIAS_RPL (gettimeofday, int, ++ (struct timeval *restrict, void *restrict)); ++# else ++# if !@HAVE_GETTIMEOFDAY@ ++_GL_FUNCDECL_SYS (gettimeofday, int, ++ (struct timeval *restrict, void *restrict) ++ _GL_ARG_NONNULL ((1))); ++# endif ++/* Need to cast, because on glibc systems, by default, the second argument is ++ struct timezone *. */ ++_GL_CXXALIAS_SYS_CAST (gettimeofday, int, ++ (struct timeval *restrict, void *restrict)); ++# endif ++_GL_CXXALIASWARN (gettimeofday); ++#elif defined GNULIB_POSIXCHECK ++# undef gettimeofday ++# if HAVE_RAW_DECL_GETTIMEOFDAY ++_GL_WARN_ON_USE (gettimeofday, "gettimeofday is unportable - " ++ "use gnulib module gettimeofday for portability"); ++# endif ++#endif ++ ++/* Hide some function declarations from . */ ++ ++#if defined _MSC_VER && @HAVE_WINSOCK2_H@ ++# if !defined _@GUARD_PREFIX@_UNISTD_H ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# undef close ++# define close close_used_without_including_unistd_h ++# else ++ _GL_WARN_ON_USE (close, ++ "close() used without including "); ++# endif ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# undef gethostname ++# define gethostname gethostname_used_without_including_unistd_h ++# else ++ _GL_WARN_ON_USE (gethostname, ++ "gethostname() used without including "); ++# endif ++# endif ++# if !defined _@GUARD_PREFIX@_SYS_SOCKET_H ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# undef socket ++# define socket socket_used_without_including_sys_socket_h ++# undef connect ++# define connect connect_used_without_including_sys_socket_h ++# undef accept ++# define accept accept_used_without_including_sys_socket_h ++# undef bind ++# define bind bind_used_without_including_sys_socket_h ++# undef getpeername ++# define getpeername getpeername_used_without_including_sys_socket_h ++# undef getsockname ++# define getsockname getsockname_used_without_including_sys_socket_h ++# undef getsockopt ++# define getsockopt getsockopt_used_without_including_sys_socket_h ++# undef listen ++# define listen listen_used_without_including_sys_socket_h ++# undef recv ++# define recv recv_used_without_including_sys_socket_h ++# undef send ++# define send send_used_without_including_sys_socket_h ++# undef recvfrom ++# define recvfrom recvfrom_used_without_including_sys_socket_h ++# undef sendto ++# define sendto sendto_used_without_including_sys_socket_h ++# undef setsockopt ++# define setsockopt setsockopt_used_without_including_sys_socket_h ++# undef shutdown ++# define shutdown shutdown_used_without_including_sys_socket_h ++# else ++ _GL_WARN_ON_USE (socket, ++ "socket() used without including "); ++ _GL_WARN_ON_USE (connect, ++ "connect() used without including "); ++ _GL_WARN_ON_USE (accept, ++ "accept() used without including "); ++ _GL_WARN_ON_USE (bind, ++ "bind() used without including "); ++ _GL_WARN_ON_USE (getpeername, ++ "getpeername() used without including "); ++ _GL_WARN_ON_USE (getsockname, ++ "getsockname() used without including "); ++ _GL_WARN_ON_USE (getsockopt, ++ "getsockopt() used without including "); ++ _GL_WARN_ON_USE (listen, ++ "listen() used without including "); ++ _GL_WARN_ON_USE (recv, ++ "recv() used without including "); ++ _GL_WARN_ON_USE (send, ++ "send() used without including "); ++ _GL_WARN_ON_USE (recvfrom, ++ "recvfrom() used without including "); ++ _GL_WARN_ON_USE (sendto, ++ "sendto() used without including "); ++ _GL_WARN_ON_USE (setsockopt, ++ "setsockopt() used without including "); ++ _GL_WARN_ON_USE (shutdown, ++ "shutdown() used without including "); ++# endif ++# endif ++# if !defined _@GUARD_PREFIX@_SYS_SELECT_H ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# undef select ++# define select select_used_without_including_sys_select_h ++# else ++ _GL_WARN_ON_USE (select, ++ "select() used without including "); ++# endif ++# endif ++#endif ++ ++#endif /* _@GUARD_PREFIX@_SYS_TIME_H */ ++#endif /* _CYGWIN_SYS_TIME_H */ ++#endif /* _@GUARD_PREFIX@_SYS_TIME_H */ +diff --git a/grub-core/gnulib/sys_types.in.h b/grub-core/gnulib/sys_types.in.h +index d7da35623b1..9520c09030c 100644 +--- a/grub-core/gnulib/sys_types.in.h ++++ b/grub-core/gnulib/sys_types.in.h +@@ -23,7 +23,9 @@ + #ifndef _@GUARD_PREFIX@_SYS_TYPES_H + + /* The include_next requires a split double-inclusion guard. */ ++# define _GL_INCLUDING_SYS_TYPES_H + #@INCLUDE_NEXT@ @NEXT_SYS_TYPES_H@ ++# undef _GL_INCLUDING_SYS_TYPES_H + + #ifndef _@GUARD_PREFIX@_SYS_TYPES_H + #define _@GUARD_PREFIX@_SYS_TYPES_H +diff --git a/grub-core/gnulib/time.h b/grub-core/gnulib/time.h +new file mode 100644 +index 00000000000..b9203d5569a +--- /dev/null ++++ b/grub-core/gnulib/time.h +@@ -0,0 +1,586 @@ ++/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ ++/* A more-standard . ++ ++ Copyright (C) 2007-2014 Free Software Foundation, Inc. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3, or (at your option) ++ any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, see . */ ++ ++#if __GNUC__ >= 3 ++#pragma GCC system_header ++#endif ++ ++ ++/* Don't get in the way of glibc when it includes time.h merely to ++ declare a few standard symbols, rather than to declare all the ++ symbols. Also, Solaris 8 eventually includes itself ++ recursively; if that is happening, just include the system ++ without adding our own declarations. */ ++#if (defined __need_time_t || defined __need_clock_t \ ++ || defined __need_timespec \ ++ || defined _GL_TIME_H) ++ ++# include_next ++ ++#else ++ ++# define _GL_TIME_H ++ ++# include_next ++ ++/* NetBSD 5.0 mis-defines NULL. */ ++# include ++ ++/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ ++#ifndef _GL_CXXDEFS_H ++#define _GL_CXXDEFS_H ++ ++/* The three most frequent use cases of these macros are: ++ ++ * For providing a substitute for a function that is missing on some ++ platforms, but is declared and works fine on the platforms on which ++ it exists: ++ ++ #if @GNULIB_FOO@ ++ # if !@HAVE_FOO@ ++ _GL_FUNCDECL_SYS (foo, ...); ++ # endif ++ _GL_CXXALIAS_SYS (foo, ...); ++ _GL_CXXALIASWARN (foo); ++ #elif defined GNULIB_POSIXCHECK ++ ... ++ #endif ++ ++ * For providing a replacement for a function that exists on all platforms, ++ but is broken/insufficient and needs to be replaced on some platforms: ++ ++ #if @GNULIB_FOO@ ++ # if @REPLACE_FOO@ ++ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++ # undef foo ++ # define foo rpl_foo ++ # endif ++ _GL_FUNCDECL_RPL (foo, ...); ++ _GL_CXXALIAS_RPL (foo, ...); ++ # else ++ _GL_CXXALIAS_SYS (foo, ...); ++ # endif ++ _GL_CXXALIASWARN (foo); ++ #elif defined GNULIB_POSIXCHECK ++ ... ++ #endif ++ ++ * For providing a replacement for a function that exists on some platforms ++ but is broken/insufficient and needs to be replaced on some of them and ++ is additionally either missing or undeclared on some other platforms: ++ ++ #if @GNULIB_FOO@ ++ # if @REPLACE_FOO@ ++ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++ # undef foo ++ # define foo rpl_foo ++ # endif ++ _GL_FUNCDECL_RPL (foo, ...); ++ _GL_CXXALIAS_RPL (foo, ...); ++ # else ++ # if !@HAVE_FOO@ or if !@HAVE_DECL_FOO@ ++ _GL_FUNCDECL_SYS (foo, ...); ++ # endif ++ _GL_CXXALIAS_SYS (foo, ...); ++ # endif ++ _GL_CXXALIASWARN (foo); ++ #elif defined GNULIB_POSIXCHECK ++ ... ++ #endif ++*/ ++ ++/* _GL_EXTERN_C declaration; ++ performs the declaration with C linkage. */ ++#if defined __cplusplus ++# define _GL_EXTERN_C extern "C" ++#else ++# define _GL_EXTERN_C extern ++#endif ++ ++/* _GL_FUNCDECL_RPL (func, rettype, parameters_and_attributes); ++ declares a replacement function, named rpl_func, with the given prototype, ++ consisting of return type, parameters, and attributes. ++ Example: ++ _GL_FUNCDECL_RPL (open, int, (const char *filename, int flags, ...) ++ _GL_ARG_NONNULL ((1))); ++ */ ++#define _GL_FUNCDECL_RPL(func,rettype,parameters_and_attributes) \ ++ _GL_FUNCDECL_RPL_1 (rpl_##func, rettype, parameters_and_attributes) ++#define _GL_FUNCDECL_RPL_1(rpl_func,rettype,parameters_and_attributes) \ ++ _GL_EXTERN_C rettype rpl_func parameters_and_attributes ++ ++/* _GL_FUNCDECL_SYS (func, rettype, parameters_and_attributes); ++ declares the system function, named func, with the given prototype, ++ consisting of return type, parameters, and attributes. ++ Example: ++ _GL_FUNCDECL_SYS (open, int, (const char *filename, int flags, ...) ++ _GL_ARG_NONNULL ((1))); ++ */ ++#define _GL_FUNCDECL_SYS(func,rettype,parameters_and_attributes) \ ++ _GL_EXTERN_C rettype func parameters_and_attributes ++ ++/* _GL_CXXALIAS_RPL (func, rettype, parameters); ++ declares a C++ alias called GNULIB_NAMESPACE::func ++ that redirects to rpl_func, if GNULIB_NAMESPACE is defined. ++ Example: ++ _GL_CXXALIAS_RPL (open, int, (const char *filename, int flags, ...)); ++ */ ++#define _GL_CXXALIAS_RPL(func,rettype,parameters) \ ++ _GL_CXXALIAS_RPL_1 (func, rpl_##func, rettype, parameters) ++#if defined __cplusplus && defined GNULIB_NAMESPACE ++# define _GL_CXXALIAS_RPL_1(func,rpl_func,rettype,parameters) \ ++ namespace GNULIB_NAMESPACE \ ++ { \ ++ rettype (*const func) parameters = ::rpl_func; \ ++ } \ ++ _GL_EXTERN_C int _gl_cxxalias_dummy ++#else ++# define _GL_CXXALIAS_RPL_1(func,rpl_func,rettype,parameters) \ ++ _GL_EXTERN_C int _gl_cxxalias_dummy ++#endif ++ ++/* _GL_CXXALIAS_RPL_CAST_1 (func, rpl_func, rettype, parameters); ++ is like _GL_CXXALIAS_RPL_1 (func, rpl_func, rettype, parameters); ++ except that the C function rpl_func may have a slightly different ++ declaration. A cast is used to silence the "invalid conversion" error ++ that would otherwise occur. */ ++#if defined __cplusplus && defined GNULIB_NAMESPACE ++# define _GL_CXXALIAS_RPL_CAST_1(func,rpl_func,rettype,parameters) \ ++ namespace GNULIB_NAMESPACE \ ++ { \ ++ rettype (*const func) parameters = \ ++ reinterpret_cast(::rpl_func); \ ++ } \ ++ _GL_EXTERN_C int _gl_cxxalias_dummy ++#else ++# define _GL_CXXALIAS_RPL_CAST_1(func,rpl_func,rettype,parameters) \ ++ _GL_EXTERN_C int _gl_cxxalias_dummy ++#endif ++ ++/* _GL_CXXALIAS_SYS (func, rettype, parameters); ++ declares a C++ alias called GNULIB_NAMESPACE::func ++ that redirects to the system provided function func, if GNULIB_NAMESPACE ++ is defined. ++ Example: ++ _GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...)); ++ */ ++#if defined __cplusplus && defined GNULIB_NAMESPACE ++ /* If we were to write ++ rettype (*const func) parameters = ::func; ++ like above in _GL_CXXALIAS_RPL_1, the compiler could optimize calls ++ better (remove an indirection through a 'static' pointer variable), ++ but then the _GL_CXXALIASWARN macro below would cause a warning not only ++ for uses of ::func but also for uses of GNULIB_NAMESPACE::func. */ ++# define _GL_CXXALIAS_SYS(func,rettype,parameters) \ ++ namespace GNULIB_NAMESPACE \ ++ { \ ++ static rettype (*func) parameters = ::func; \ ++ } \ ++ _GL_EXTERN_C int _gl_cxxalias_dummy ++#else ++# define _GL_CXXALIAS_SYS(func,rettype,parameters) \ ++ _GL_EXTERN_C int _gl_cxxalias_dummy ++#endif ++ ++/* _GL_CXXALIAS_SYS_CAST (func, rettype, parameters); ++ is like _GL_CXXALIAS_SYS (func, rettype, parameters); ++ except that the C function func may have a slightly different declaration. ++ A cast is used to silence the "invalid conversion" error that would ++ otherwise occur. */ ++#if defined __cplusplus && defined GNULIB_NAMESPACE ++# define _GL_CXXALIAS_SYS_CAST(func,rettype,parameters) \ ++ namespace GNULIB_NAMESPACE \ ++ { \ ++ static rettype (*func) parameters = \ ++ reinterpret_cast(::func); \ ++ } \ ++ _GL_EXTERN_C int _gl_cxxalias_dummy ++#else ++# define _GL_CXXALIAS_SYS_CAST(func,rettype,parameters) \ ++ _GL_EXTERN_C int _gl_cxxalias_dummy ++#endif ++ ++/* _GL_CXXALIAS_SYS_CAST2 (func, rettype, parameters, rettype2, parameters2); ++ is like _GL_CXXALIAS_SYS (func, rettype, parameters); ++ except that the C function is picked among a set of overloaded functions, ++ namely the one with rettype2 and parameters2. Two consecutive casts ++ are used to silence the "cannot find a match" and "invalid conversion" ++ errors that would otherwise occur. */ ++#if defined __cplusplus && defined GNULIB_NAMESPACE ++ /* The outer cast must be a reinterpret_cast. ++ The inner cast: When the function is defined as a set of overloaded ++ functions, it works as a static_cast<>, choosing the designated variant. ++ When the function is defined as a single variant, it works as a ++ reinterpret_cast<>. The parenthesized cast syntax works both ways. */ ++# define _GL_CXXALIAS_SYS_CAST2(func,rettype,parameters,rettype2,parameters2) \ ++ namespace GNULIB_NAMESPACE \ ++ { \ ++ static rettype (*func) parameters = \ ++ reinterpret_cast( \ ++ (rettype2(*)parameters2)(::func)); \ ++ } \ ++ _GL_EXTERN_C int _gl_cxxalias_dummy ++#else ++# define _GL_CXXALIAS_SYS_CAST2(func,rettype,parameters,rettype2,parameters2) \ ++ _GL_EXTERN_C int _gl_cxxalias_dummy ++#endif ++ ++/* _GL_CXXALIASWARN (func); ++ causes a warning to be emitted when ::func is used but not when ++ GNULIB_NAMESPACE::func is used. func must be defined without overloaded ++ variants. */ ++#if defined __cplusplus && defined GNULIB_NAMESPACE ++# define _GL_CXXALIASWARN(func) \ ++ _GL_CXXALIASWARN_1 (func, GNULIB_NAMESPACE) ++# define _GL_CXXALIASWARN_1(func,namespace) \ ++ _GL_CXXALIASWARN_2 (func, namespace) ++/* To work around GCC bug , ++ we enable the warning only when not optimizing. */ ++# if !__OPTIMIZE__ ++# define _GL_CXXALIASWARN_2(func,namespace) \ ++ _GL_WARN_ON_USE (func, \ ++ "The symbol ::" #func " refers to the system function. " \ ++ "Use " #namespace "::" #func " instead.") ++# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING ++# define _GL_CXXALIASWARN_2(func,namespace) \ ++ extern __typeof__ (func) func ++# else ++# define _GL_CXXALIASWARN_2(func,namespace) \ ++ _GL_EXTERN_C int _gl_cxxalias_dummy ++# endif ++#else ++# define _GL_CXXALIASWARN(func) \ ++ _GL_EXTERN_C int _gl_cxxalias_dummy ++#endif ++ ++/* _GL_CXXALIASWARN1 (func, rettype, parameters_and_attributes); ++ causes a warning to be emitted when the given overloaded variant of ::func ++ is used but not when GNULIB_NAMESPACE::func is used. */ ++#if defined __cplusplus && defined GNULIB_NAMESPACE ++# define _GL_CXXALIASWARN1(func,rettype,parameters_and_attributes) \ ++ _GL_CXXALIASWARN1_1 (func, rettype, parameters_and_attributes, \ ++ GNULIB_NAMESPACE) ++# define _GL_CXXALIASWARN1_1(func,rettype,parameters_and_attributes,namespace) \ ++ _GL_CXXALIASWARN1_2 (func, rettype, parameters_and_attributes, namespace) ++/* To work around GCC bug , ++ we enable the warning only when not optimizing. */ ++# if !__OPTIMIZE__ ++# define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \ ++ _GL_WARN_ON_USE_CXX (func, rettype, parameters_and_attributes, \ ++ "The symbol ::" #func " refers to the system function. " \ ++ "Use " #namespace "::" #func " instead.") ++# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING ++# define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \ ++ extern __typeof__ (func) func ++# else ++# define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \ ++ _GL_EXTERN_C int _gl_cxxalias_dummy ++# endif ++#else ++# define _GL_CXXALIASWARN1(func,rettype,parameters_and_attributes) \ ++ _GL_EXTERN_C int _gl_cxxalias_dummy ++#endif ++ ++#endif /* _GL_CXXDEFS_H */ ++ ++/* The definition of _GL_ARG_NONNULL is copied here. */ ++/* _GL_ARG_NONNULL((n,...,m)) tells the compiler and static analyzer tools ++ that the values passed as arguments n, ..., m must be non-NULL pointers. ++ n = 1 stands for the first argument, n = 2 for the second argument etc. */ ++#ifndef _GL_ARG_NONNULL ++# if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || __GNUC__ > 3 ++# define _GL_ARG_NONNULL(params) __attribute__ ((__nonnull__ params)) ++# else ++# define _GL_ARG_NONNULL(params) ++# endif ++#endif ++ ++/* The definition of _GL_WARN_ON_USE is copied here. */ ++#ifndef _GL_WARN_ON_USE ++ ++# if 4 < __GNUC__ || (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) ++/* A compiler attribute is available in gcc versions 4.3.0 and later. */ ++# define _GL_WARN_ON_USE(function, message) \ ++extern __typeof__ (function) function __attribute__ ((__warning__ (message))) ++# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING ++/* Verify the existence of the function. */ ++# define _GL_WARN_ON_USE(function, message) \ ++extern __typeof__ (function) function ++# else /* Unsupported. */ ++# define _GL_WARN_ON_USE(function, message) \ ++_GL_WARN_EXTERN_C int _gl_warn_on_use ++# endif ++#endif ++ ++/* _GL_WARN_ON_USE_CXX (function, rettype, parameters_and_attributes, "string") ++ is like _GL_WARN_ON_USE (function, "string"), except that the function is ++ declared with the given prototype, consisting of return type, parameters, ++ and attributes. ++ This variant is useful for overloaded functions in C++. _GL_WARN_ON_USE does ++ not work in this case. */ ++#ifndef _GL_WARN_ON_USE_CXX ++# if 4 < __GNUC__ || (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) ++# define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \ ++extern rettype function parameters_and_attributes \ ++ __attribute__ ((__warning__ (msg))) ++# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING ++/* Verify the existence of the function. */ ++# define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \ ++extern rettype function parameters_and_attributes ++# else /* Unsupported. */ ++# define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \ ++_GL_WARN_EXTERN_C int _gl_warn_on_use ++# endif ++#endif ++ ++/* _GL_WARN_EXTERN_C declaration; ++ performs the declaration with C linkage. */ ++#ifndef _GL_WARN_EXTERN_C ++# if defined __cplusplus ++# define _GL_WARN_EXTERN_C extern "C" ++# else ++# define _GL_WARN_EXTERN_C extern ++# endif ++#endif ++ ++/* Some systems don't define struct timespec (e.g., AIX 4.1, Ultrix 4.3). ++ Or they define it with the wrong member names or define it in ++ (e.g., FreeBSD circa 1997). Stock Mingw prior to 3.0 does not define it, ++ but the pthreads-win32 library defines it in . */ ++# if ! 1 ++# if 0 ++# include ++# elif 0 ++# include ++# else ++ ++# ifdef __cplusplus ++extern "C" { ++# endif ++ ++# if !GNULIB_defined_struct_timespec ++# undef timespec ++# define timespec rpl_timespec ++struct timespec ++{ ++ time_t tv_sec; ++ long int tv_nsec; ++}; ++# define GNULIB_defined_struct_timespec 1 ++# endif ++ ++# ifdef __cplusplus ++} ++# endif ++ ++# endif ++# endif ++ ++# if !GNULIB_defined_struct_time_t_must_be_integral ++/* Per http://austingroupbugs.net/view.php?id=327, POSIX requires ++ time_t to be an integer type, even though C99 permits floating ++ point. We don't know of any implementation that uses floating ++ point, and it is much easier to write code that doesn't have to ++ worry about that corner case, so we force the issue. */ ++struct __time_t_must_be_integral { ++ unsigned int __floating_time_t_unsupported : (time_t) 1; ++}; ++# define GNULIB_defined_struct_time_t_must_be_integral 1 ++# endif ++ ++/* Sleep for at least RQTP seconds unless interrupted, If interrupted, ++ return -1 and store the remaining time into RMTP. See ++ . */ ++# if 0 ++# if GNULIB_PORTCHECK ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# define nanosleep rpl_nanosleep ++# endif ++_GL_FUNCDECL_RPL (nanosleep, int, ++ (struct timespec const *__rqtp, struct timespec *__rmtp) ++ _GL_ARG_NONNULL ((1))); ++_GL_CXXALIAS_RPL (nanosleep, int, ++ (struct timespec const *__rqtp, struct timespec *__rmtp)); ++# else ++# if ! 1 ++_GL_FUNCDECL_SYS (nanosleep, int, ++ (struct timespec const *__rqtp, struct timespec *__rmtp) ++ _GL_ARG_NONNULL ((1))); ++# endif ++_GL_CXXALIAS_SYS (nanosleep, int, ++ (struct timespec const *__rqtp, struct timespec *__rmtp)); ++# endif ++_GL_CXXALIASWARN (nanosleep); ++# endif ++ ++/* Return the 'time_t' representation of TP and normalize TP. */ ++# if 0 ++# if GNULIB_PORTCHECK ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# define mktime rpl_mktime ++# endif ++_GL_FUNCDECL_RPL (mktime, time_t, (struct tm *__tp) _GL_ARG_NONNULL ((1))); ++_GL_CXXALIAS_RPL (mktime, time_t, (struct tm *__tp)); ++# else ++_GL_CXXALIAS_SYS (mktime, time_t, (struct tm *__tp)); ++# endif ++_GL_CXXALIASWARN (mktime); ++# endif ++ ++/* Convert TIMER to RESULT, assuming local time and UTC respectively. See ++ and ++ . */ ++# if 0 ++# if GNULIB_PORTCHECK ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# undef localtime_r ++# define localtime_r rpl_localtime_r ++# endif ++_GL_FUNCDECL_RPL (localtime_r, struct tm *, (time_t const *restrict __timer, ++ struct tm *restrict __result) ++ _GL_ARG_NONNULL ((1, 2))); ++_GL_CXXALIAS_RPL (localtime_r, struct tm *, (time_t const *restrict __timer, ++ struct tm *restrict __result)); ++# else ++# if ! 1 ++_GL_FUNCDECL_SYS (localtime_r, struct tm *, (time_t const *restrict __timer, ++ struct tm *restrict __result) ++ _GL_ARG_NONNULL ((1, 2))); ++# endif ++_GL_CXXALIAS_SYS (localtime_r, struct tm *, (time_t const *restrict __timer, ++ struct tm *restrict __result)); ++# endif ++# if 1 ++_GL_CXXALIASWARN (localtime_r); ++# endif ++# if GNULIB_PORTCHECK ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# undef gmtime_r ++# define gmtime_r rpl_gmtime_r ++# endif ++_GL_FUNCDECL_RPL (gmtime_r, struct tm *, (time_t const *restrict __timer, ++ struct tm *restrict __result) ++ _GL_ARG_NONNULL ((1, 2))); ++_GL_CXXALIAS_RPL (gmtime_r, struct tm *, (time_t const *restrict __timer, ++ struct tm *restrict __result)); ++# else ++# if ! 1 ++_GL_FUNCDECL_SYS (gmtime_r, struct tm *, (time_t const *restrict __timer, ++ struct tm *restrict __result) ++ _GL_ARG_NONNULL ((1, 2))); ++# endif ++_GL_CXXALIAS_SYS (gmtime_r, struct tm *, (time_t const *restrict __timer, ++ struct tm *restrict __result)); ++# endif ++# if 1 ++_GL_CXXALIASWARN (gmtime_r); ++# endif ++# endif ++ ++/* Convert TIMER to RESULT, assuming local time and UTC respectively. See ++ and ++ . */ ++# if 1 ++# if 0 ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# undef localtime ++# define localtime rpl_localtime ++# endif ++_GL_FUNCDECL_RPL (localtime, struct tm *, (time_t const *__timer) ++ _GL_ARG_NONNULL ((1))); ++_GL_CXXALIAS_RPL (localtime, struct tm *, (time_t const *__timer)); ++# else ++_GL_CXXALIAS_SYS (localtime, struct tm *, (time_t const *__timer)); ++# endif ++_GL_CXXALIASWARN (localtime); ++# endif ++ ++# if 1 ++# if 0 ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# undef gmtime ++# define gmtime rpl_gmtime ++# endif ++_GL_FUNCDECL_RPL (gmtime, struct tm *, (time_t const *__timer) ++ _GL_ARG_NONNULL ((1))); ++_GL_CXXALIAS_RPL (gmtime, struct tm *, (time_t const *__timer)); ++# else ++_GL_CXXALIAS_SYS (gmtime, struct tm *, (time_t const *__timer)); ++# endif ++_GL_CXXALIASWARN (gmtime); ++# endif ++ ++/* Parse BUF as a time stamp, assuming FORMAT specifies its layout, and store ++ the resulting broken-down time into TM. See ++ . */ ++# if 0 ++# if ! 1 ++_GL_FUNCDECL_SYS (strptime, char *, (char const *restrict __buf, ++ char const *restrict __format, ++ struct tm *restrict __tm) ++ _GL_ARG_NONNULL ((1, 2, 3))); ++# endif ++_GL_CXXALIAS_SYS (strptime, char *, (char const *restrict __buf, ++ char const *restrict __format, ++ struct tm *restrict __tm)); ++_GL_CXXALIASWARN (strptime); ++# endif ++ ++/* Convert TM to a time_t value, assuming UTC. */ ++# if 0 ++# if GNULIB_PORTCHECK ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# undef timegm ++# define timegm rpl_timegm ++# endif ++_GL_FUNCDECL_RPL (timegm, time_t, (struct tm *__tm) _GL_ARG_NONNULL ((1))); ++_GL_CXXALIAS_RPL (timegm, time_t, (struct tm *__tm)); ++# else ++# if ! 1 ++_GL_FUNCDECL_SYS (timegm, time_t, (struct tm *__tm) _GL_ARG_NONNULL ((1))); ++# endif ++_GL_CXXALIAS_SYS (timegm, time_t, (struct tm *__tm)); ++# endif ++_GL_CXXALIASWARN (timegm); ++# endif ++ ++/* Encourage applications to avoid unsafe functions that can overrun ++ buffers when given outlandish struct tm values. Portable ++ applications should use strftime (or even sprintf) instead. */ ++# if defined GNULIB_POSIXCHECK ++# undef asctime ++_GL_WARN_ON_USE (asctime, "asctime can overrun buffers in some cases - " ++ "better use strftime (or even sprintf) instead"); ++# endif ++# if defined GNULIB_POSIXCHECK ++# undef asctime_r ++_GL_WARN_ON_USE (asctime, "asctime_r can overrun buffers in some cases - " ++ "better use strftime (or even sprintf) instead"); ++# endif ++# if defined GNULIB_POSIXCHECK ++# undef ctime ++_GL_WARN_ON_USE (asctime, "ctime can overrun buffers in some cases - " ++ "better use strftime (or even sprintf) instead"); ++# endif ++# if defined GNULIB_POSIXCHECK ++# undef ctime_r ++_GL_WARN_ON_USE (asctime, "ctime_r can overrun buffers in some cases - " ++ "better use strftime (or even sprintf) instead"); ++# endif ++ ++#endif +diff --git a/grub-core/gnulib/time.in.h b/grub-core/gnulib/time.in.h +new file mode 100644 +index 00000000000..81abdf46e0b +--- /dev/null ++++ b/grub-core/gnulib/time.in.h +@@ -0,0 +1,274 @@ ++/* A more-standard . ++ ++ Copyright (C) 2007-2014 Free Software Foundation, Inc. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3, or (at your option) ++ any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, see . */ ++ ++#if __GNUC__ >= 3 ++@PRAGMA_SYSTEM_HEADER@ ++#endif ++@PRAGMA_COLUMNS@ ++ ++/* Don't get in the way of glibc when it includes time.h merely to ++ declare a few standard symbols, rather than to declare all the ++ symbols. Also, Solaris 8 eventually includes itself ++ recursively; if that is happening, just include the system ++ without adding our own declarations. */ ++#if (defined __need_time_t || defined __need_clock_t \ ++ || defined __need_timespec \ ++ || defined _@GUARD_PREFIX@_TIME_H) ++ ++# @INCLUDE_NEXT@ @NEXT_TIME_H@ ++ ++#else ++ ++# define _@GUARD_PREFIX@_TIME_H ++ ++# @INCLUDE_NEXT@ @NEXT_TIME_H@ ++ ++/* NetBSD 5.0 mis-defines NULL. */ ++# include ++ ++/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ ++ ++/* The definition of _GL_ARG_NONNULL is copied here. */ ++ ++/* The definition of _GL_WARN_ON_USE is copied here. */ ++ ++/* Some systems don't define struct timespec (e.g., AIX 4.1, Ultrix 4.3). ++ Or they define it with the wrong member names or define it in ++ (e.g., FreeBSD circa 1997). Stock Mingw prior to 3.0 does not define it, ++ but the pthreads-win32 library defines it in . */ ++# if ! @TIME_H_DEFINES_STRUCT_TIMESPEC@ ++# if @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@ ++# include ++# elif @PTHREAD_H_DEFINES_STRUCT_TIMESPEC@ ++# include ++# else ++ ++# ifdef __cplusplus ++extern "C" { ++# endif ++ ++# if !GNULIB_defined_struct_timespec ++# undef timespec ++# define timespec rpl_timespec ++struct timespec ++{ ++ time_t tv_sec; ++ long int tv_nsec; ++}; ++# define GNULIB_defined_struct_timespec 1 ++# endif ++ ++# ifdef __cplusplus ++} ++# endif ++ ++# endif ++# endif ++ ++# if !GNULIB_defined_struct_time_t_must_be_integral ++/* Per http://austingroupbugs.net/view.php?id=327, POSIX requires ++ time_t to be an integer type, even though C99 permits floating ++ point. We don't know of any implementation that uses floating ++ point, and it is much easier to write code that doesn't have to ++ worry about that corner case, so we force the issue. */ ++struct __time_t_must_be_integral { ++ unsigned int __floating_time_t_unsupported : (time_t) 1; ++}; ++# define GNULIB_defined_struct_time_t_must_be_integral 1 ++# endif ++ ++/* Sleep for at least RQTP seconds unless interrupted, If interrupted, ++ return -1 and store the remaining time into RMTP. See ++ . */ ++# if @GNULIB_NANOSLEEP@ ++# if @REPLACE_NANOSLEEP@ ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# define nanosleep rpl_nanosleep ++# endif ++_GL_FUNCDECL_RPL (nanosleep, int, ++ (struct timespec const *__rqtp, struct timespec *__rmtp) ++ _GL_ARG_NONNULL ((1))); ++_GL_CXXALIAS_RPL (nanosleep, int, ++ (struct timespec const *__rqtp, struct timespec *__rmtp)); ++# else ++# if ! @HAVE_NANOSLEEP@ ++_GL_FUNCDECL_SYS (nanosleep, int, ++ (struct timespec const *__rqtp, struct timespec *__rmtp) ++ _GL_ARG_NONNULL ((1))); ++# endif ++_GL_CXXALIAS_SYS (nanosleep, int, ++ (struct timespec const *__rqtp, struct timespec *__rmtp)); ++# endif ++_GL_CXXALIASWARN (nanosleep); ++# endif ++ ++/* Return the 'time_t' representation of TP and normalize TP. */ ++# if @GNULIB_MKTIME@ ++# if @REPLACE_MKTIME@ ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# define mktime rpl_mktime ++# endif ++_GL_FUNCDECL_RPL (mktime, time_t, (struct tm *__tp) _GL_ARG_NONNULL ((1))); ++_GL_CXXALIAS_RPL (mktime, time_t, (struct tm *__tp)); ++# else ++_GL_CXXALIAS_SYS (mktime, time_t, (struct tm *__tp)); ++# endif ++_GL_CXXALIASWARN (mktime); ++# endif ++ ++/* Convert TIMER to RESULT, assuming local time and UTC respectively. See ++ and ++ . */ ++# if @GNULIB_TIME_R@ ++# if @REPLACE_LOCALTIME_R@ ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# undef localtime_r ++# define localtime_r rpl_localtime_r ++# endif ++_GL_FUNCDECL_RPL (localtime_r, struct tm *, (time_t const *restrict __timer, ++ struct tm *restrict __result) ++ _GL_ARG_NONNULL ((1, 2))); ++_GL_CXXALIAS_RPL (localtime_r, struct tm *, (time_t const *restrict __timer, ++ struct tm *restrict __result)); ++# else ++# if ! @HAVE_DECL_LOCALTIME_R@ ++_GL_FUNCDECL_SYS (localtime_r, struct tm *, (time_t const *restrict __timer, ++ struct tm *restrict __result) ++ _GL_ARG_NONNULL ((1, 2))); ++# endif ++_GL_CXXALIAS_SYS (localtime_r, struct tm *, (time_t const *restrict __timer, ++ struct tm *restrict __result)); ++# endif ++# if @HAVE_DECL_LOCALTIME_R@ ++_GL_CXXALIASWARN (localtime_r); ++# endif ++# if @REPLACE_LOCALTIME_R@ ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# undef gmtime_r ++# define gmtime_r rpl_gmtime_r ++# endif ++_GL_FUNCDECL_RPL (gmtime_r, struct tm *, (time_t const *restrict __timer, ++ struct tm *restrict __result) ++ _GL_ARG_NONNULL ((1, 2))); ++_GL_CXXALIAS_RPL (gmtime_r, struct tm *, (time_t const *restrict __timer, ++ struct tm *restrict __result)); ++# else ++# if ! @HAVE_DECL_LOCALTIME_R@ ++_GL_FUNCDECL_SYS (gmtime_r, struct tm *, (time_t const *restrict __timer, ++ struct tm *restrict __result) ++ _GL_ARG_NONNULL ((1, 2))); ++# endif ++_GL_CXXALIAS_SYS (gmtime_r, struct tm *, (time_t const *restrict __timer, ++ struct tm *restrict __result)); ++# endif ++# if @HAVE_DECL_LOCALTIME_R@ ++_GL_CXXALIASWARN (gmtime_r); ++# endif ++# endif ++ ++/* Convert TIMER to RESULT, assuming local time and UTC respectively. See ++ and ++ . */ ++# if @GNULIB_GETTIMEOFDAY@ ++# if @REPLACE_LOCALTIME@ ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# undef localtime ++# define localtime rpl_localtime ++# endif ++_GL_FUNCDECL_RPL (localtime, struct tm *, (time_t const *__timer) ++ _GL_ARG_NONNULL ((1))); ++_GL_CXXALIAS_RPL (localtime, struct tm *, (time_t const *__timer)); ++# else ++_GL_CXXALIAS_SYS (localtime, struct tm *, (time_t const *__timer)); ++# endif ++_GL_CXXALIASWARN (localtime); ++# endif ++ ++# if @GNULIB_GETTIMEOFDAY@ ++# if @REPLACE_GMTIME@ ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# undef gmtime ++# define gmtime rpl_gmtime ++# endif ++_GL_FUNCDECL_RPL (gmtime, struct tm *, (time_t const *__timer) ++ _GL_ARG_NONNULL ((1))); ++_GL_CXXALIAS_RPL (gmtime, struct tm *, (time_t const *__timer)); ++# else ++_GL_CXXALIAS_SYS (gmtime, struct tm *, (time_t const *__timer)); ++# endif ++_GL_CXXALIASWARN (gmtime); ++# endif ++ ++/* Parse BUF as a time stamp, assuming FORMAT specifies its layout, and store ++ the resulting broken-down time into TM. See ++ . */ ++# if @GNULIB_STRPTIME@ ++# if ! @HAVE_STRPTIME@ ++_GL_FUNCDECL_SYS (strptime, char *, (char const *restrict __buf, ++ char const *restrict __format, ++ struct tm *restrict __tm) ++ _GL_ARG_NONNULL ((1, 2, 3))); ++# endif ++_GL_CXXALIAS_SYS (strptime, char *, (char const *restrict __buf, ++ char const *restrict __format, ++ struct tm *restrict __tm)); ++_GL_CXXALIASWARN (strptime); ++# endif ++ ++/* Convert TM to a time_t value, assuming UTC. */ ++# if @GNULIB_TIMEGM@ ++# if @REPLACE_TIMEGM@ ++# if !(defined __cplusplus && defined GNULIB_NAMESPACE) ++# undef timegm ++# define timegm rpl_timegm ++# endif ++_GL_FUNCDECL_RPL (timegm, time_t, (struct tm *__tm) _GL_ARG_NONNULL ((1))); ++_GL_CXXALIAS_RPL (timegm, time_t, (struct tm *__tm)); ++# else ++# if ! @HAVE_TIMEGM@ ++_GL_FUNCDECL_SYS (timegm, time_t, (struct tm *__tm) _GL_ARG_NONNULL ((1))); ++# endif ++_GL_CXXALIAS_SYS (timegm, time_t, (struct tm *__tm)); ++# endif ++_GL_CXXALIASWARN (timegm); ++# endif ++ ++/* Encourage applications to avoid unsafe functions that can overrun ++ buffers when given outlandish struct tm values. Portable ++ applications should use strftime (or even sprintf) instead. */ ++# if defined GNULIB_POSIXCHECK ++# undef asctime ++_GL_WARN_ON_USE (asctime, "asctime can overrun buffers in some cases - " ++ "better use strftime (or even sprintf) instead"); ++# endif ++# if defined GNULIB_POSIXCHECK ++# undef asctime_r ++_GL_WARN_ON_USE (asctime, "asctime_r can overrun buffers in some cases - " ++ "better use strftime (or even sprintf) instead"); ++# endif ++# if defined GNULIB_POSIXCHECK ++# undef ctime ++_GL_WARN_ON_USE (asctime, "ctime can overrun buffers in some cases - " ++ "better use strftime (or even sprintf) instead"); ++# endif ++# if defined GNULIB_POSIXCHECK ++# undef ctime_r ++_GL_WARN_ON_USE (asctime, "ctime_r can overrun buffers in some cases - " ++ "better use strftime (or even sprintf) instead"); ++# endif ++ ++#endif +diff --git a/include/grub/osdep/hostfile_aros.h b/include/grub/osdep/hostfile_aros.h +index a059c0fa40a..161fbb7bdfd 100644 +--- a/include/grub/osdep/hostfile_aros.h ++++ b/include/grub/osdep/hostfile_aros.h +@@ -68,6 +68,12 @@ grub_util_rename (const char *from, const char *to) + return rename (from, to); + } + ++static inline ssize_t ++grub_util_readlink (const char *name, char *buf, size_t bufsize) ++{ ++ return readlink(name, buf, bufsize); ++} ++ + #define grub_util_mkdir(a) mkdir ((a), 0755) + + struct grub_util_fd +diff --git a/include/grub/osdep/hostfile_unix.h b/include/grub/osdep/hostfile_unix.h +index 9ffe46fa3ca..17cd3aa8b30 100644 +--- a/include/grub/osdep/hostfile_unix.h ++++ b/include/grub/osdep/hostfile_unix.h +@@ -71,6 +71,12 @@ grub_util_rename (const char *from, const char *to) + return rename (from, to); + } + ++static inline ssize_t ++grub_util_readlink (const char *name, char *buf, size_t bufsize) ++{ ++ return readlink(name, buf, bufsize); ++} ++ + #define grub_util_mkdir(a) mkdir ((a), 0755) + + #if defined (__NetBSD__) +diff --git a/include/grub/osdep/hostfile_windows.h b/include/grub/osdep/hostfile_windows.h +index bf6451b6db4..8c92d0591bb 100644 +--- a/include/grub/osdep/hostfile_windows.h ++++ b/include/grub/osdep/hostfile_windows.h +@@ -41,6 +41,8 @@ typedef struct grub_util_fd_dir *grub_util_fd_dir_t; + + int + grub_util_rename (const char *from, const char *to); ++ssize_t ++grub_util_readlink (const char *name, char *buf, size_t bufsize); + int + grub_util_unlink (const char *name); + void +diff --git a/grub-core/gnulib/Makefile.am b/grub-core/gnulib/Makefile.am +index 3444397fe37..b7c5e60e1c3 100644 +--- a/grub-core/gnulib/Makefile.am ++++ b/grub-core/gnulib/Makefile.am +@@ -21,7 +21,7 @@ + # the same distribution terms as the rest of that program. + # + # Generated by gnulib-tool. +-# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=grub-core/gnulib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files argp error fnmatch getdelim getline gettext progname regex ++# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=grub-core/gnulib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files argp error fnmatch getdelim getline gettext progname readlink regex + + AUTOMAKE_OPTIONS = 1.5 gnits subdir-objects + +@@ -326,6 +326,15 @@ libgnu_a_SOURCES += gettext.h + + ## end gnulib module gettext-h + ++## begin gnulib module gettimeofday ++ ++ ++EXTRA_DIST += gettimeofday.c ++ ++EXTRA_libgnu_a_SOURCES += gettimeofday.c ++ ++## end gnulib module gettimeofday ++ + ## begin gnulib module havelib + + +@@ -596,6 +605,13 @@ EXTRA_libgnu_a_SOURCES += nl_langinfo.c + + ## end gnulib module nl_langinfo + ++## begin gnulib module pathmax ++ ++ ++EXTRA_DIST += pathmax.h ++ ++## end gnulib module pathmax ++ + ## begin gnulib module progname + + libgnu_a_SOURCES += progname.h progname.c +@@ -611,6 +627,15 @@ EXTRA_libgnu_a_SOURCES += rawmemchr.c + + ## end gnulib module rawmemchr + ++## begin gnulib module readlink ++ ++ ++EXTRA_DIST += readlink.c ++ ++EXTRA_libgnu_a_SOURCES += readlink.c ++ ++## end gnulib module readlink ++ + ## begin gnulib module realloc-posix + + +@@ -725,6 +750,15 @@ EXTRA_DIST += $(top_srcdir)/build-aux/snippet/warn-on-use.h + + ## end gnulib module snippet/warn-on-use + ++## begin gnulib module stat ++ ++ ++EXTRA_DIST += stat.c ++ ++EXTRA_libgnu_a_SOURCES += stat.c ++ ++## end gnulib module stat ++ + ## begin gnulib module stdalign + + BUILT_SOURCES += $(STDALIGN_H) +@@ -1280,6 +1314,102 @@ libgnu_a_SOURCES += strnlen1.h strnlen1.c + + ## end gnulib module strnlen1 + ++## begin gnulib module sys_stat ++ ++BUILT_SOURCES += sys/stat.h ++ ++# We need the following in order to create when the system ++# has one that is incomplete. ++sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) ++ $(AM_V_at)$(MKDIR_P) sys ++ $(AM_V_GEN)rm -f $@-t $@ && \ ++ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ ++ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ ++ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ ++ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ ++ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ ++ -e 's|@''NEXT_SYS_STAT_H''@|$(NEXT_SYS_STAT_H)|g' \ ++ -e 's|@''WINDOWS_64_BIT_ST_SIZE''@|$(WINDOWS_64_BIT_ST_SIZE)|g' \ ++ -e 's/@''GNULIB_FCHMODAT''@/$(GNULIB_FCHMODAT)/g' \ ++ -e 's/@''GNULIB_FSTAT''@/$(GNULIB_FSTAT)/g' \ ++ -e 's/@''GNULIB_FSTATAT''@/$(GNULIB_FSTATAT)/g' \ ++ -e 's/@''GNULIB_FUTIMENS''@/$(GNULIB_FUTIMENS)/g' \ ++ -e 's/@''GNULIB_LCHMOD''@/$(GNULIB_LCHMOD)/g' \ ++ -e 's/@''GNULIB_LSTAT''@/$(GNULIB_LSTAT)/g' \ ++ -e 's/@''GNULIB_MKDIRAT''@/$(GNULIB_MKDIRAT)/g' \ ++ -e 's/@''GNULIB_MKFIFO''@/$(GNULIB_MKFIFO)/g' \ ++ -e 's/@''GNULIB_MKFIFOAT''@/$(GNULIB_MKFIFOAT)/g' \ ++ -e 's/@''GNULIB_MKNOD''@/$(GNULIB_MKNOD)/g' \ ++ -e 's/@''GNULIB_MKNODAT''@/$(GNULIB_MKNODAT)/g' \ ++ -e 's/@''GNULIB_STAT''@/$(GNULIB_STAT)/g' \ ++ -e 's/@''GNULIB_UTIMENSAT''@/$(GNULIB_UTIMENSAT)/g' \ ++ -e 's|@''HAVE_FCHMODAT''@|$(HAVE_FCHMODAT)|g' \ ++ -e 's|@''HAVE_FSTATAT''@|$(HAVE_FSTATAT)|g' \ ++ -e 's|@''HAVE_FUTIMENS''@|$(HAVE_FUTIMENS)|g' \ ++ -e 's|@''HAVE_LCHMOD''@|$(HAVE_LCHMOD)|g' \ ++ -e 's|@''HAVE_LSTAT''@|$(HAVE_LSTAT)|g' \ ++ -e 's|@''HAVE_MKDIRAT''@|$(HAVE_MKDIRAT)|g' \ ++ -e 's|@''HAVE_MKFIFO''@|$(HAVE_MKFIFO)|g' \ ++ -e 's|@''HAVE_MKFIFOAT''@|$(HAVE_MKFIFOAT)|g' \ ++ -e 's|@''HAVE_MKNOD''@|$(HAVE_MKNOD)|g' \ ++ -e 's|@''HAVE_MKNODAT''@|$(HAVE_MKNODAT)|g' \ ++ -e 's|@''HAVE_UTIMENSAT''@|$(HAVE_UTIMENSAT)|g' \ ++ -e 's|@''REPLACE_FSTAT''@|$(REPLACE_FSTAT)|g' \ ++ -e 's|@''REPLACE_FSTATAT''@|$(REPLACE_FSTATAT)|g' \ ++ -e 's|@''REPLACE_FUTIMENS''@|$(REPLACE_FUTIMENS)|g' \ ++ -e 's|@''REPLACE_LSTAT''@|$(REPLACE_LSTAT)|g' \ ++ -e 's|@''REPLACE_MKDIR''@|$(REPLACE_MKDIR)|g' \ ++ -e 's|@''REPLACE_MKFIFO''@|$(REPLACE_MKFIFO)|g' \ ++ -e 's|@''REPLACE_MKNOD''@|$(REPLACE_MKNOD)|g' \ ++ -e 's|@''REPLACE_STAT''@|$(REPLACE_STAT)|g' \ ++ -e 's|@''REPLACE_UTIMENSAT''@|$(REPLACE_UTIMENSAT)|g' \ ++ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ ++ -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ ++ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ ++ < $(srcdir)/sys_stat.in.h; \ ++ } > $@-t && \ ++ mv $@-t $@ ++MOSTLYCLEANFILES += sys/stat.h sys/stat.h-t ++MOSTLYCLEANDIRS += sys ++ ++EXTRA_DIST += sys_stat.in.h ++ ++## end gnulib module sys_stat ++ ++## begin gnulib module sys_time ++ ++BUILT_SOURCES += sys/time.h ++ ++# We need the following in order to create when the system ++# doesn't have one that works with the given compiler. ++sys/time.h: sys_time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) ++ $(AM_V_at)$(MKDIR_P) sys ++ $(AM_V_GEN)rm -f $@-t $@ && \ ++ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ ++ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ ++ -e 's/@''HAVE_SYS_TIME_H''@/$(HAVE_SYS_TIME_H)/g' \ ++ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ ++ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ ++ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ ++ -e 's|@''NEXT_SYS_TIME_H''@|$(NEXT_SYS_TIME_H)|g' \ ++ -e 's/@''GNULIB_GETTIMEOFDAY''@/$(GNULIB_GETTIMEOFDAY)/g' \ ++ -e 's|@''HAVE_WINSOCK2_H''@|$(HAVE_WINSOCK2_H)|g' \ ++ -e 's/@''HAVE_GETTIMEOFDAY''@/$(HAVE_GETTIMEOFDAY)/g' \ ++ -e 's/@''HAVE_STRUCT_TIMEVAL''@/$(HAVE_STRUCT_TIMEVAL)/g' \ ++ -e 's/@''REPLACE_GETTIMEOFDAY''@/$(REPLACE_GETTIMEOFDAY)/g' \ ++ -e 's/@''REPLACE_STRUCT_TIMEVAL''@/$(REPLACE_STRUCT_TIMEVAL)/g' \ ++ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ ++ -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ ++ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ ++ < $(srcdir)/sys_time.in.h; \ ++ } > $@-t && \ ++ mv $@-t $@ ++MOSTLYCLEANFILES += sys/time.h sys/time.h-t ++ ++EXTRA_DIST += sys_time.in.h ++ ++## end gnulib module sys_time ++ + ## begin gnulib module sys_types + + BUILT_SOURCES += sys/types.h +@@ -1334,6 +1464,51 @@ EXTRA_DIST += sysexits.in.h + + ## end gnulib module sysexits + ++## begin gnulib module time ++ ++BUILT_SOURCES += time.h ++ ++# We need the following in order to create when the system ++# doesn't have one that works with the given compiler. ++time.h: time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) ++ $(AM_V_GEN)rm -f $@-t $@ && \ ++ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ ++ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ ++ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ ++ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ ++ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ ++ -e 's|@''NEXT_TIME_H''@|$(NEXT_TIME_H)|g' \ ++ -e 's/@''GNULIB_GETTIMEOFDAY''@/$(GNULIB_GETTIMEOFDAY)/g' \ ++ -e 's/@''GNULIB_MKTIME''@/$(GNULIB_MKTIME)/g' \ ++ -e 's/@''GNULIB_NANOSLEEP''@/$(GNULIB_NANOSLEEP)/g' \ ++ -e 's/@''GNULIB_STRPTIME''@/$(GNULIB_STRPTIME)/g' \ ++ -e 's/@''GNULIB_TIMEGM''@/$(GNULIB_TIMEGM)/g' \ ++ -e 's/@''GNULIB_TIME_R''@/$(GNULIB_TIME_R)/g' \ ++ -e 's|@''HAVE_DECL_LOCALTIME_R''@|$(HAVE_DECL_LOCALTIME_R)|g' \ ++ -e 's|@''HAVE_NANOSLEEP''@|$(HAVE_NANOSLEEP)|g' \ ++ -e 's|@''HAVE_STRPTIME''@|$(HAVE_STRPTIME)|g' \ ++ -e 's|@''HAVE_TIMEGM''@|$(HAVE_TIMEGM)|g' \ ++ -e 's|@''REPLACE_GMTIME''@|$(REPLACE_GMTIME)|g' \ ++ -e 's|@''REPLACE_LOCALTIME''@|$(REPLACE_LOCALTIME)|g' \ ++ -e 's|@''REPLACE_LOCALTIME_R''@|$(REPLACE_LOCALTIME_R)|g' \ ++ -e 's|@''REPLACE_MKTIME''@|$(REPLACE_MKTIME)|g' \ ++ -e 's|@''REPLACE_NANOSLEEP''@|$(REPLACE_NANOSLEEP)|g' \ ++ -e 's|@''REPLACE_TIMEGM''@|$(REPLACE_TIMEGM)|g' \ ++ -e 's|@''PTHREAD_H_DEFINES_STRUCT_TIMESPEC''@|$(PTHREAD_H_DEFINES_STRUCT_TIMESPEC)|g' \ ++ -e 's|@''SYS_TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(SYS_TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \ ++ -e 's|@''TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \ ++ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ ++ -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ ++ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ ++ < $(srcdir)/time.in.h; \ ++ } > $@-t && \ ++ mv $@-t $@ ++MOSTLYCLEANFILES += time.h time.h-t ++ ++EXTRA_DIST += time.in.h ++ ++## end gnulib module time ++ + ## begin gnulib module unistd + + BUILT_SOURCES += unistd.h +diff --git a/m4/gettimeofday.m4 b/m4/gettimeofday.m4 +new file mode 100644 +index 00000000000..1c2d66ee261 +--- /dev/null ++++ b/m4/gettimeofday.m4 +@@ -0,0 +1,138 @@ ++# serial 21 ++ ++# Copyright (C) 2001-2003, 2005, 2007, 2009-2014 Free Software Foundation, Inc. ++# This file is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. ++ ++dnl From Jim Meyering. ++ ++AC_DEFUN([gl_FUNC_GETTIMEOFDAY], ++[ ++ AC_REQUIRE([AC_C_RESTRICT]) ++ AC_REQUIRE([gl_HEADER_SYS_TIME_H]) ++ AC_REQUIRE([gl_HEADER_SYS_TIME_H_DEFAULTS]) ++ AC_CHECK_FUNCS_ONCE([gettimeofday]) ++ ++ gl_gettimeofday_timezone=void ++ if test $ac_cv_func_gettimeofday != yes; then ++ HAVE_GETTIMEOFDAY=0 ++ else ++ gl_FUNC_GETTIMEOFDAY_CLOBBER ++ AC_CACHE_CHECK([for gettimeofday with POSIX signature], ++ [gl_cv_func_gettimeofday_posix_signature], ++ [AC_COMPILE_IFELSE( ++ [AC_LANG_PROGRAM( ++ [[#include ++ struct timeval c; ++ int gettimeofday (struct timeval *restrict, void *restrict); ++ ]], ++ [[/* glibc uses struct timezone * rather than the POSIX void * ++ if _GNU_SOURCE is defined. However, since the only portable ++ use of gettimeofday uses NULL as the second parameter, and ++ since the glibc definition is actually more typesafe, it is ++ not worth wrapping this to get a compliant signature. */ ++ int (*f) (struct timeval *restrict, void *restrict) ++ = gettimeofday; ++ int x = f (&c, 0); ++ return !(x | c.tv_sec | c.tv_usec); ++ ]])], ++ [gl_cv_func_gettimeofday_posix_signature=yes], ++ [AC_COMPILE_IFELSE( ++ [AC_LANG_PROGRAM( ++ [[#include ++int gettimeofday (struct timeval *restrict, struct timezone *restrict); ++ ]])], ++ [gl_cv_func_gettimeofday_posix_signature=almost], ++ [gl_cv_func_gettimeofday_posix_signature=no])])]) ++ if test $gl_cv_func_gettimeofday_posix_signature = almost; then ++ gl_gettimeofday_timezone='struct timezone' ++ elif test $gl_cv_func_gettimeofday_posix_signature != yes; then ++ REPLACE_GETTIMEOFDAY=1 ++ fi ++ dnl If we override 'struct timeval', we also have to override gettimeofday. ++ if test $REPLACE_STRUCT_TIMEVAL = 1; then ++ REPLACE_GETTIMEOFDAY=1 ++ fi ++ m4_ifdef([gl_FUNC_TZSET_CLOBBER], [ ++ gl_FUNC_TZSET_CLOBBER ++ case "$gl_cv_func_tzset_clobber" in ++ *yes) ++ REPLACE_GETTIMEOFDAY=1 ++ gl_GETTIMEOFDAY_REPLACE_LOCALTIME ++ AC_DEFINE([tzset], [rpl_tzset], ++ [Define to rpl_tzset if the wrapper function should be used.]) ++ AC_DEFINE([TZSET_CLOBBERS_LOCALTIME], [1], ++ [Define if tzset clobbers localtime's static buffer.]) ++ ;; ++ esac ++ ]) ++ fi ++ AC_DEFINE_UNQUOTED([GETTIMEOFDAY_TIMEZONE], [$gl_gettimeofday_timezone], ++ [Define this to 'void' or 'struct timezone' to match the system's ++ declaration of the second argument to gettimeofday.]) ++]) ++ ++ ++dnl See if gettimeofday clobbers the static buffer that localtime uses ++dnl for its return value. The gettimeofday function from Mac OS X 10.0.4 ++dnl (i.e., Darwin 1.3.7) has this problem. ++dnl ++dnl If it does, then arrange to use gettimeofday and localtime only via ++dnl the wrapper functions that work around the problem. ++ ++AC_DEFUN([gl_FUNC_GETTIMEOFDAY_CLOBBER], ++[ ++ AC_REQUIRE([gl_HEADER_SYS_TIME_H]) ++ AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles ++ ++ AC_CACHE_CHECK([whether gettimeofday clobbers localtime buffer], ++ [gl_cv_func_gettimeofday_clobber], ++ [AC_RUN_IFELSE( ++ [AC_LANG_PROGRAM( ++ [[#include ++ #include ++ #include ++ #include ++ ]], ++ [[ ++ time_t t = 0; ++ struct tm *lt; ++ struct tm saved_lt; ++ struct timeval tv; ++ lt = localtime (&t); ++ saved_lt = *lt; ++ gettimeofday (&tv, NULL); ++ return memcmp (lt, &saved_lt, sizeof (struct tm)) != 0; ++ ]])], ++ [gl_cv_func_gettimeofday_clobber=no], ++ [gl_cv_func_gettimeofday_clobber=yes], ++ [# When cross-compiling: ++ case "$host_os" in ++ # Guess all is fine on glibc systems. ++ *-gnu*) gl_cv_func_gettimeofday_clobber="guessing no" ;; ++ # If we don't know, assume the worst. ++ *) gl_cv_func_gettimeofday_clobber="guessing yes" ;; ++ esac ++ ])]) ++ ++ case "$gl_cv_func_gettimeofday_clobber" in ++ *yes) ++ REPLACE_GETTIMEOFDAY=1 ++ gl_GETTIMEOFDAY_REPLACE_LOCALTIME ++ AC_DEFINE([GETTIMEOFDAY_CLOBBERS_LOCALTIME], [1], ++ [Define if gettimeofday clobbers the localtime buffer.]) ++ ;; ++ esac ++]) ++ ++AC_DEFUN([gl_GETTIMEOFDAY_REPLACE_LOCALTIME], [ ++ REPLACE_GMTIME=1 ++ REPLACE_LOCALTIME=1 ++]) ++ ++# Prerequisites of lib/gettimeofday.c. ++AC_DEFUN([gl_PREREQ_GETTIMEOFDAY], [ ++ AC_CHECK_HEADERS([sys/timeb.h]) ++ AC_CHECK_FUNCS([_ftime]) ++]) +diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4 +index 408918440b6..ef2ec5bcce0 100644 +--- a/m4/gnulib-cache.m4 ++++ b/m4/gnulib-cache.m4 +@@ -27,7 +27,7 @@ + + + # Specification in the form of a command-line invocation: +-# gnulib-tool --import --dir=. --lib=libgnu --source-base=grub-core/gnulib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files argp error fnmatch getdelim getline gettext progname regex ++# gnulib-tool --import --dir=. --lib=libgnu --source-base=grub-core/gnulib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files argp error fnmatch getdelim getline gettext progname readlink regex + + # Specification in the form of a few gnulib-tool.m4 macro invocations: + gl_LOCAL_DIR([]) +@@ -39,6 +39,7 @@ gl_MODULES([ + getline + gettext + progname ++ readlink + regex + ]) + gl_AVOID([]) +diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 +index 7a19f60d85e..66fd0eda901 100644 +--- a/m4/gnulib-comp.m4 ++++ b/m4/gnulib-comp.m4 +@@ -60,10 +60,13 @@ AC_DEFUN([gl_EARLY], + # Code from module getopt-posix: + # Code from module gettext: + # Code from module gettext-h: ++ # Code from module gettimeofday: + # Code from module havelib: + # Code from module include_next: + # Code from module intprops: + # Code from module langinfo: ++ # Code from module largefile: ++ AC_REQUIRE([AC_SYS_LARGEFILE]) + # Code from module localcharset: + # Code from module locale: + # Code from module localeconv: +@@ -81,8 +84,10 @@ AC_DEFUN([gl_EARLY], + # Code from module multiarch: + # Code from module nl_langinfo: + # Code from module nocrash: ++ # Code from module pathmax: + # Code from module progname: + # Code from module rawmemchr: ++ # Code from module readlink: + # Code from module realloc-posix: + # Code from module regex: + # Code from module size_max: +@@ -92,6 +97,7 @@ AC_DEFUN([gl_EARLY], + # Code from module snippet/c++defs: + # Code from module snippet/warn-on-use: + # Code from module ssize_t: ++ # Code from module stat: + # Code from module stdalign: + # Code from module stdbool: + # Code from module stddef: +@@ -108,8 +114,11 @@ AC_DEFUN([gl_EARLY], + # Code from module strndup: + # Code from module strnlen: + # Code from module strnlen1: ++ # Code from module sys_stat: ++ # Code from module sys_time: + # Code from module sys_types: + # Code from module sysexits: ++ # Code from module time: + # Code from module unistd: + # Code from module unitypes: + # Code from module uniwidth/base: +@@ -211,7 +220,14 @@ AC_DEFUN([gl_INIT], + AM_GNU_GETTEXT_VERSION([0.18.1]) + AC_SUBST([LIBINTL]) + AC_SUBST([LTLIBINTL]) ++ gl_FUNC_GETTIMEOFDAY ++ if test $HAVE_GETTIMEOFDAY = 0 || test $REPLACE_GETTIMEOFDAY = 1; then ++ AC_LIBOBJ([gettimeofday]) ++ gl_PREREQ_GETTIMEOFDAY ++ fi ++ gl_SYS_TIME_MODULE_INDICATOR([gettimeofday]) + gl_LANGINFO_H ++ AC_REQUIRE([gl_LARGEFILE]) + gl_LOCALCHARSET + LOCALCHARSET_TESTS_ENVIRONMENT="CHARSETALIASDIR=\"\$(abs_top_builddir)/$gl_source_base\"" + AC_SUBST([LOCALCHARSET_TESTS_ENVIRONMENT]) +@@ -284,6 +300,7 @@ AC_DEFUN([gl_INIT], + AC_LIBOBJ([nl_langinfo]) + fi + gl_LANGINFO_MODULE_INDICATOR([nl_langinfo]) ++ gl_PATHMAX + AC_CHECK_DECLS([program_invocation_name], [], [], [#include ]) + AC_CHECK_DECLS([program_invocation_short_name], [], [], [#include ]) + gl_FUNC_RAWMEMCHR +@@ -292,6 +309,12 @@ AC_DEFUN([gl_INIT], + gl_PREREQ_RAWMEMCHR + fi + gl_STRING_MODULE_INDICATOR([rawmemchr]) ++ gl_FUNC_READLINK ++ if test $HAVE_READLINK = 0 || test $REPLACE_READLINK = 1; then ++ AC_LIBOBJ([readlink]) ++ gl_PREREQ_READLINK ++ fi ++ gl_UNISTD_MODULE_INDICATOR([readlink]) + gl_FUNC_REALLOC_POSIX + if test $REPLACE_REALLOC = 1; then + AC_LIBOBJ([realloc]) +@@ -309,6 +332,12 @@ AC_DEFUN([gl_INIT], + fi + gl_UNISTD_MODULE_INDICATOR([sleep]) + gt_TYPE_SSIZE_T ++ gl_FUNC_STAT ++ if test $REPLACE_STAT = 1; then ++ AC_LIBOBJ([stat]) ++ gl_PREREQ_STAT ++ fi ++ gl_SYS_STAT_MODULE_INDICATOR([stat]) + gl_STDALIGN_H + AM_STDBOOL_H + gl_STDDEF_H +@@ -355,9 +384,14 @@ AC_DEFUN([gl_INIT], + gl_PREREQ_STRNLEN + fi + gl_STRING_MODULE_INDICATOR([strnlen]) ++ gl_HEADER_SYS_STAT_H ++ AC_PROG_MKDIR_P ++ gl_HEADER_SYS_TIME_H ++ AC_PROG_MKDIR_P + gl_SYS_TYPES_H + AC_PROG_MKDIR_P + gl_SYSEXITS ++ gl_HEADER_TIME_H + gl_UNISTD_H + gl_LIBUNISTRING_LIBHEADER([0.9], [unitypes.h]) + gl_LIBUNISTRING_LIBHEADER([0.9], [uniwidth.h]) +@@ -562,6 +596,7 @@ AC_DEFUN([gl_FILE_LIST], [ + lib/getopt1.c + lib/getopt_int.h + lib/gettext.h ++ lib/gettimeofday.c + lib/intprops.h + lib/itold.c + lib/langinfo.in.h +@@ -587,6 +622,7 @@ AC_DEFUN([gl_FILE_LIST], [ + lib/msvc-nothrow.c + lib/msvc-nothrow.h + lib/nl_langinfo.c ++ lib/pathmax.h + lib/printf-args.c + lib/printf-args.h + lib/printf-parse.c +@@ -595,6 +631,7 @@ AC_DEFUN([gl_FILE_LIST], [ + lib/progname.h + lib/rawmemchr.c + lib/rawmemchr.valgrind ++ lib/readlink.c + lib/realloc.c + lib/ref-add.sin + lib/ref-del.sin +@@ -606,6 +643,7 @@ AC_DEFUN([gl_FILE_LIST], [ + lib/regexec.c + lib/size_max.h + lib/sleep.c ++ lib/stat.c + lib/stdalign.in.h + lib/stdbool.in.h + lib/stddef.in.h +@@ -627,8 +665,11 @@ AC_DEFUN([gl_FILE_LIST], [ + lib/strnlen.c + lib/strnlen1.c + lib/strnlen1.h ++ lib/sys_stat.in.h ++ lib/sys_time.in.h + lib/sys_types.in.h + lib/sysexits.in.h ++ lib/time.in.h + lib/unistd.c + lib/unistd.in.h + lib/unitypes.in.h +@@ -667,6 +708,7 @@ AC_DEFUN([gl_FILE_LIST], [ + m4/getline.m4 + m4/getopt.m4 + m4/gettext.m4 ++ m4/gettimeofday.m4 + m4/glibc2.m4 + m4/glibc21.m4 + m4/gnulib-common.m4 +@@ -681,6 +723,7 @@ AC_DEFUN([gl_FILE_LIST], [ + m4/inttypes-pri.m4 + m4/inttypes_h.m4 + m4/langinfo_h.m4 ++ m4/largefile.m4 + m4/lcmessage.m4 + m4/lib-ld.m4 + m4/lib-link.m4 +@@ -712,16 +755,19 @@ AC_DEFUN([gl_FILE_LIST], [ + m4/nls.m4 + m4/nocrash.m4 + m4/off_t.m4 ++ m4/pathmax.m4 + m4/po.m4 + m4/printf-posix.m4 + m4/printf.m4 + m4/progtest.m4 + m4/rawmemchr.m4 ++ m4/readlink.m4 + m4/realloc.m4 + m4/regex.m4 + m4/size_max.m4 + m4/sleep.m4 + m4/ssize_t.m4 ++ m4/stat.m4 + m4/stdalign.m4 + m4/stdbool.m4 + m4/stddef_h.m4 +@@ -737,9 +783,12 @@ AC_DEFUN([gl_FILE_LIST], [ + m4/strndup.m4 + m4/strnlen.m4 + m4/sys_socket_h.m4 ++ m4/sys_stat_h.m4 ++ m4/sys_time_h.m4 + m4/sys_types_h.m4 + m4/sysexits.m4 + m4/threadlib.m4 ++ m4/time_h.m4 + m4/uintmax_t.m4 + m4/unistd_h.m4 + m4/vasnprintf.m4 +diff --git a/m4/largefile.m4 b/m4/largefile.m4 +new file mode 100644 +index 00000000000..a1b564ad9af +--- /dev/null ++++ b/m4/largefile.m4 +@@ -0,0 +1,146 @@ ++# Enable large files on systems where this is not the default. ++ ++# Copyright 1992-1996, 1998-2014 Free Software Foundation, Inc. ++# This file is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. ++ ++# The following implementation works around a problem in autoconf <= 2.69; ++# AC_SYS_LARGEFILE does not configure for large inodes on Mac OS X 10.5, ++# or configures them incorrectly in some cases. ++m4_version_prereq([2.70], [] ,[ ++ ++# _AC_SYS_LARGEFILE_TEST_INCLUDES ++# ------------------------------- ++m4_define([_AC_SYS_LARGEFILE_TEST_INCLUDES], ++[@%:@include ++ /* Check that off_t can represent 2**63 - 1 correctly. ++ We can't simply define LARGE_OFF_T to be 9223372036854775807, ++ since some C++ compilers masquerading as C compilers ++ incorrectly reject 9223372036854775807. */ ++@%:@define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) ++ int off_t_is_large[[(LARGE_OFF_T % 2147483629 == 721 ++ && LARGE_OFF_T % 2147483647 == 1) ++ ? 1 : -1]];[]dnl ++]) ++ ++ ++# _AC_SYS_LARGEFILE_MACRO_VALUE(C-MACRO, VALUE, ++# CACHE-VAR, ++# DESCRIPTION, ++# PROLOGUE, [FUNCTION-BODY]) ++# -------------------------------------------------------- ++m4_define([_AC_SYS_LARGEFILE_MACRO_VALUE], ++[AC_CACHE_CHECK([for $1 value needed for large files], [$3], ++[while :; do ++ m4_ifval([$6], [AC_LINK_IFELSE], [AC_COMPILE_IFELSE])( ++ [AC_LANG_PROGRAM([$5], [$6])], ++ [$3=no; break]) ++ m4_ifval([$6], [AC_LINK_IFELSE], [AC_COMPILE_IFELSE])( ++ [AC_LANG_PROGRAM([@%:@define $1 $2 ++$5], [$6])], ++ [$3=$2; break]) ++ $3=unknown ++ break ++done]) ++case $$3 in #( ++ no | unknown) ;; ++ *) AC_DEFINE_UNQUOTED([$1], [$$3], [$4]);; ++esac ++rm -rf conftest*[]dnl ++])# _AC_SYS_LARGEFILE_MACRO_VALUE ++ ++ ++# AC_SYS_LARGEFILE ++# ---------------- ++# By default, many hosts won't let programs access large files; ++# one must use special compiler options to get large-file access to work. ++# For more details about this brain damage please see: ++# http://www.unix-systems.org/version2/whatsnew/lfs20mar.html ++AC_DEFUN([AC_SYS_LARGEFILE], ++[AC_ARG_ENABLE(largefile, ++ [ --disable-largefile omit support for large files]) ++if test "$enable_largefile" != no; then ++ ++ AC_CACHE_CHECK([for special C compiler options needed for large files], ++ ac_cv_sys_largefile_CC, ++ [ac_cv_sys_largefile_CC=no ++ if test "$GCC" != yes; then ++ ac_save_CC=$CC ++ while :; do ++ # IRIX 6.2 and later do not support large files by default, ++ # so use the C compiler's -n32 option if that helps. ++ AC_LANG_CONFTEST([AC_LANG_PROGRAM([_AC_SYS_LARGEFILE_TEST_INCLUDES])]) ++ AC_COMPILE_IFELSE([], [break]) ++ CC="$CC -n32" ++ AC_COMPILE_IFELSE([], [ac_cv_sys_largefile_CC=' -n32'; break]) ++ break ++ done ++ CC=$ac_save_CC ++ rm -f conftest.$ac_ext ++ fi]) ++ if test "$ac_cv_sys_largefile_CC" != no; then ++ CC=$CC$ac_cv_sys_largefile_CC ++ fi ++ ++ _AC_SYS_LARGEFILE_MACRO_VALUE(_FILE_OFFSET_BITS, 64, ++ ac_cv_sys_file_offset_bits, ++ [Number of bits in a file offset, on hosts where this is settable.], ++ [_AC_SYS_LARGEFILE_TEST_INCLUDES]) ++ if test $ac_cv_sys_file_offset_bits = unknown; then ++ _AC_SYS_LARGEFILE_MACRO_VALUE(_LARGE_FILES, 1, ++ ac_cv_sys_large_files, ++ [Define for large files, on AIX-style hosts.], ++ [_AC_SYS_LARGEFILE_TEST_INCLUDES]) ++ fi ++ ++ AC_DEFINE([_DARWIN_USE_64_BIT_INODE], [1], ++ [Enable large inode numbers on Mac OS X 10.5.]) ++fi ++])# AC_SYS_LARGEFILE ++])# m4_version_prereq 2.70 ++ ++# Enable large files on systems where this is implemented by Gnulib, not by the ++# system headers. ++# Set the variables WINDOWS_64_BIT_OFF_T, WINDOWS_64_BIT_ST_SIZE if Gnulib ++# overrides ensure that off_t or 'struct size.st_size' are 64-bit, respectively. ++AC_DEFUN([gl_LARGEFILE], ++[ ++ AC_REQUIRE([AC_CANONICAL_HOST]) ++ case "$host_os" in ++ mingw*) ++ dnl Native Windows. ++ dnl mingw64 defines off_t to a 64-bit type already, if ++ dnl _FILE_OFFSET_BITS=64, which is ensured by AC_SYS_LARGEFILE. ++ AC_CACHE_CHECK([for 64-bit off_t], [gl_cv_type_off_t_64], ++ [AC_COMPILE_IFELSE( ++ [AC_LANG_PROGRAM( ++ [[#include ++ int verify_off_t_size[sizeof (off_t) >= 8 ? 1 : -1]; ++ ]], ++ [[]])], ++ [gl_cv_type_off_t_64=yes], [gl_cv_type_off_t_64=no]) ++ ]) ++ if test $gl_cv_type_off_t_64 = no; then ++ WINDOWS_64_BIT_OFF_T=1 ++ else ++ WINDOWS_64_BIT_OFF_T=0 ++ fi ++ dnl But all native Windows platforms (including mingw64) have a 32-bit ++ dnl st_size member in 'struct stat'. ++ WINDOWS_64_BIT_ST_SIZE=1 ++ ;; ++ *) ++ dnl Nothing to do on gnulib's side. ++ dnl A 64-bit off_t is ++ dnl - already the default on Mac OS X, FreeBSD, NetBSD, OpenBSD, IRIX, ++ dnl OSF/1, Cygwin, ++ dnl - enabled by _FILE_OFFSET_BITS=64 (ensured by AC_SYS_LARGEFILE) on ++ dnl glibc, HP-UX, Solaris, ++ dnl - enabled by _LARGE_FILES=1 (ensured by AC_SYS_LARGEFILE) on AIX, ++ dnl - impossible to achieve on Minix 3.1.8. ++ WINDOWS_64_BIT_OFF_T=0 ++ WINDOWS_64_BIT_ST_SIZE=0 ++ ;; ++ esac ++]) +diff --git a/m4/pathmax.m4 b/m4/pathmax.m4 +new file mode 100644 +index 00000000000..114f91f04b5 +--- /dev/null ++++ b/m4/pathmax.m4 +@@ -0,0 +1,42 @@ ++# pathmax.m4 serial 10 ++dnl Copyright (C) 2002-2003, 2005-2006, 2009-2014 Free Software Foundation, ++dnl Inc. ++dnl This file is free software; the Free Software Foundation ++dnl gives unlimited permission to copy and/or distribute it, ++dnl with or without modifications, as long as this notice is preserved. ++ ++AC_DEFUN([gl_PATHMAX], ++[ ++ dnl Prerequisites of lib/pathmax.h. ++ AC_CHECK_HEADERS_ONCE([sys/param.h]) ++]) ++ ++# Expands to a piece of C program that defines PATH_MAX in the same way as ++# "pathmax.h" will do. ++AC_DEFUN([gl_PATHMAX_SNIPPET], [[ ++/* Arrange to define PATH_MAX, like "pathmax.h" does. */ ++#if HAVE_UNISTD_H ++# include ++#endif ++#include ++#if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN ++# include ++#endif ++#if !defined PATH_MAX && defined MAXPATHLEN ++# define PATH_MAX MAXPATHLEN ++#endif ++#ifdef __hpux ++# undef PATH_MAX ++# define PATH_MAX 1024 ++#endif ++#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ ++# undef PATH_MAX ++# define PATH_MAX 260 ++#endif ++]]) ++ ++# Prerequisites of gl_PATHMAX_SNIPPET. ++AC_DEFUN([gl_PATHMAX_SNIPPET_PREREQ], ++[ ++ AC_CHECK_HEADERS_ONCE([unistd.h sys/param.h]) ++]) +diff --git a/m4/readlink.m4 b/m4/readlink.m4 +new file mode 100644 +index 00000000000..f9ce868c2e4 +--- /dev/null ++++ b/m4/readlink.m4 +@@ -0,0 +1,71 @@ ++# readlink.m4 serial 12 ++dnl Copyright (C) 2003, 2007, 2009-2014 Free Software Foundation, Inc. ++dnl This file is free software; the Free Software Foundation ++dnl gives unlimited permission to copy and/or distribute it, ++dnl with or without modifications, as long as this notice is preserved. ++ ++AC_DEFUN([gl_FUNC_READLINK], ++[ ++ AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) ++ AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles ++ AC_CHECK_FUNCS_ONCE([readlink]) ++ if test $ac_cv_func_readlink = no; then ++ HAVE_READLINK=0 ++ else ++ AC_CACHE_CHECK([whether readlink signature is correct], ++ [gl_cv_decl_readlink_works], ++ [AC_COMPILE_IFELSE( ++ [AC_LANG_PROGRAM( ++ [[#include ++ /* Cause compilation failure if original declaration has wrong type. */ ++ ssize_t readlink (const char *, char *, size_t);]])], ++ [gl_cv_decl_readlink_works=yes], [gl_cv_decl_readlink_works=no])]) ++ dnl Solaris 9 ignores trailing slash. ++ dnl FreeBSD 7.2 dereferences only one level of links with trailing slash. ++ AC_CACHE_CHECK([whether readlink handles trailing slash correctly], ++ [gl_cv_func_readlink_works], ++ [# We have readlink, so assume ln -s works. ++ ln -s conftest.no-such conftest.link ++ ln -s conftest.link conftest.lnk2 ++ AC_RUN_IFELSE( ++ [AC_LANG_PROGRAM( ++ [[#include ++]], [[char buf[20]; ++ return readlink ("conftest.lnk2/", buf, sizeof buf) != -1;]])], ++ [gl_cv_func_readlink_works=yes], [gl_cv_func_readlink_works=no], ++ [case "$host_os" in ++ # Guess yes on glibc systems. ++ *-gnu*) gl_cv_func_readlink_works="guessing yes" ;; ++ # If we don't know, assume the worst. ++ *) gl_cv_func_readlink_works="guessing no" ;; ++ esac ++ ]) ++ rm -f conftest.link conftest.lnk2]) ++ case "$gl_cv_func_readlink_works" in ++ *yes) ++ if test "$gl_cv_decl_readlink_works" != yes; then ++ REPLACE_READLINK=1 ++ fi ++ ;; ++ *) ++ AC_DEFINE([READLINK_TRAILING_SLASH_BUG], [1], [Define to 1 if readlink ++ fails to recognize a trailing slash.]) ++ REPLACE_READLINK=1 ++ ;; ++ esac ++ fi ++]) ++ ++# Like gl_FUNC_READLINK, except prepare for separate compilation ++# (no REPLACE_READLINK, no AC_LIBOBJ). ++AC_DEFUN([gl_FUNC_READLINK_SEPARATE], ++[ ++ AC_CHECK_FUNCS_ONCE([readlink]) ++ gl_PREREQ_READLINK ++]) ++ ++# Prerequisites of lib/readlink.c. ++AC_DEFUN([gl_PREREQ_READLINK], ++[ ++ : ++]) +diff --git a/m4/stat.m4 b/m4/stat.m4 +new file mode 100644 +index 00000000000..1ae327b3684 +--- /dev/null ++++ b/m4/stat.m4 +@@ -0,0 +1,71 @@ ++# serial 11 ++ ++# Copyright (C) 2009-2014 Free Software Foundation, Inc. ++# ++# This file is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. ++ ++AC_DEFUN([gl_FUNC_STAT], ++[ ++ AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles ++ AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS]) ++ AC_CHECK_FUNCS_ONCE([lstat]) ++ dnl mingw is the only known platform where stat(".") and stat("./") differ ++ AC_CACHE_CHECK([whether stat handles trailing slashes on directories], ++ [gl_cv_func_stat_dir_slash], ++ [AC_RUN_IFELSE( ++ [AC_LANG_PROGRAM( ++ [[#include ++]], [[struct stat st; return stat (".", &st) != stat ("./", &st);]])], ++ [gl_cv_func_stat_dir_slash=yes], [gl_cv_func_stat_dir_slash=no], ++ [case $host_os in ++ mingw*) gl_cv_func_stat_dir_slash="guessing no";; ++ *) gl_cv_func_stat_dir_slash="guessing yes";; ++ esac])]) ++ dnl AIX 7.1, Solaris 9, mingw64 mistakenly succeed on stat("file/"). ++ dnl (For mingw, this is due to a broken stat() override in libmingwex.a.) ++ dnl FreeBSD 7.2 mistakenly succeeds on stat("link-to-file/"). ++ AC_CACHE_CHECK([whether stat handles trailing slashes on files], ++ [gl_cv_func_stat_file_slash], ++ [touch conftest.tmp ++ # Assume that if we have lstat, we can also check symlinks. ++ if test $ac_cv_func_lstat = yes; then ++ ln -s conftest.tmp conftest.lnk ++ fi ++ AC_RUN_IFELSE( ++ [AC_LANG_PROGRAM( ++ [[#include ++]], [[int result = 0; ++ struct stat st; ++ if (!stat ("conftest.tmp/", &st)) ++ result |= 1; ++#if HAVE_LSTAT ++ if (!stat ("conftest.lnk/", &st)) ++ result |= 2; ++#endif ++ return result; ++ ]])], ++ [gl_cv_func_stat_file_slash=yes], [gl_cv_func_stat_file_slash=no], ++ [case "$host_os" in ++ # Guess yes on glibc systems. ++ *-gnu*) gl_cv_func_stat_file_slash="guessing yes" ;; ++ # If we don't know, assume the worst. ++ *) gl_cv_func_stat_file_slash="guessing no" ;; ++ esac ++ ]) ++ rm -f conftest.tmp conftest.lnk]) ++ case $gl_cv_func_stat_dir_slash in ++ *no) REPLACE_STAT=1 ++ AC_DEFINE([REPLACE_FUNC_STAT_DIR], [1], [Define to 1 if stat needs ++ help when passed a directory name with a trailing slash]);; ++ esac ++ case $gl_cv_func_stat_file_slash in ++ *no) REPLACE_STAT=1 ++ AC_DEFINE([REPLACE_FUNC_STAT_FILE], [1], [Define to 1 if stat needs ++ help when passed a file name with a trailing slash]);; ++ esac ++]) ++ ++# Prerequisites of lib/stat.c. ++AC_DEFUN([gl_PREREQ_STAT], [:]) +diff --git a/m4/sys_stat_h.m4 b/m4/sys_stat_h.m4 +new file mode 100644 +index 00000000000..eaa7642ba31 +--- /dev/null ++++ b/m4/sys_stat_h.m4 +@@ -0,0 +1,96 @@ ++# sys_stat_h.m4 serial 28 -*- Autoconf -*- ++dnl Copyright (C) 2006-2014 Free Software Foundation, Inc. ++dnl This file is free software; the Free Software Foundation ++dnl gives unlimited permission to copy and/or distribute it, ++dnl with or without modifications, as long as this notice is preserved. ++ ++dnl From Eric Blake. ++dnl Provide a GNU-like . ++ ++AC_DEFUN([gl_HEADER_SYS_STAT_H], ++[ ++ AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS]) ++ ++ dnl Check for broken stat macros. ++ AC_REQUIRE([AC_HEADER_STAT]) ++ ++ gl_CHECK_NEXT_HEADERS([sys/stat.h]) ++ ++ dnl Ensure the type mode_t gets defined. ++ AC_REQUIRE([AC_TYPE_MODE_T]) ++ ++ dnl Whether to override 'struct stat'. ++ m4_ifdef([gl_LARGEFILE], [ ++ AC_REQUIRE([gl_LARGEFILE]) ++ ], [ ++ WINDOWS_64_BIT_ST_SIZE=0 ++ ]) ++ AC_SUBST([WINDOWS_64_BIT_ST_SIZE]) ++ if test $WINDOWS_64_BIT_ST_SIZE = 1; then ++ AC_DEFINE([_GL_WINDOWS_64_BIT_ST_SIZE], [1], ++ [Define to 1 if Gnulib overrides 'struct stat' on Windows so that ++ struct stat.st_size becomes 64-bit.]) ++ fi ++ ++ dnl Define types that are supposed to be defined in or ++ dnl . ++ AC_CHECK_TYPE([nlink_t], [], ++ [AC_DEFINE([nlink_t], [int], ++ [Define to the type of st_nlink in struct stat, or a supertype.])], ++ [#include ++ #include ]) ++ ++ dnl Check for declarations of anything we want to poison if the ++ dnl corresponding gnulib module is not in use. ++ gl_WARN_ON_USE_PREPARE([[#include ++ ]], [fchmodat fstat fstatat futimens lchmod lstat mkdirat mkfifo mkfifoat ++ mknod mknodat stat utimensat]) ++]) # gl_HEADER_SYS_STAT_H ++ ++AC_DEFUN([gl_SYS_STAT_MODULE_INDICATOR], ++[ ++ dnl Use AC_REQUIRE here, so that the default settings are expanded once only. ++ AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS]) ++ gl_MODULE_INDICATOR_SET_VARIABLE([$1]) ++ dnl Define it also as a C macro, for the benefit of the unit tests. ++ gl_MODULE_INDICATOR_FOR_TESTS([$1]) ++]) ++ ++AC_DEFUN([gl_SYS_STAT_H_DEFAULTS], ++[ ++ AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) dnl for REPLACE_FCHDIR ++ GNULIB_FCHMODAT=0; AC_SUBST([GNULIB_FCHMODAT]) ++ GNULIB_FSTAT=0; AC_SUBST([GNULIB_FSTAT]) ++ GNULIB_FSTATAT=0; AC_SUBST([GNULIB_FSTATAT]) ++ GNULIB_FUTIMENS=0; AC_SUBST([GNULIB_FUTIMENS]) ++ GNULIB_LCHMOD=0; AC_SUBST([GNULIB_LCHMOD]) ++ GNULIB_LSTAT=0; AC_SUBST([GNULIB_LSTAT]) ++ GNULIB_MKDIRAT=0; AC_SUBST([GNULIB_MKDIRAT]) ++ GNULIB_MKFIFO=0; AC_SUBST([GNULIB_MKFIFO]) ++ GNULIB_MKFIFOAT=0; AC_SUBST([GNULIB_MKFIFOAT]) ++ GNULIB_MKNOD=0; AC_SUBST([GNULIB_MKNOD]) ++ GNULIB_MKNODAT=0; AC_SUBST([GNULIB_MKNODAT]) ++ GNULIB_STAT=0; AC_SUBST([GNULIB_STAT]) ++ GNULIB_UTIMENSAT=0; AC_SUBST([GNULIB_UTIMENSAT]) ++ dnl Assume proper GNU behavior unless another module says otherwise. ++ HAVE_FCHMODAT=1; AC_SUBST([HAVE_FCHMODAT]) ++ HAVE_FSTATAT=1; AC_SUBST([HAVE_FSTATAT]) ++ HAVE_FUTIMENS=1; AC_SUBST([HAVE_FUTIMENS]) ++ HAVE_LCHMOD=1; AC_SUBST([HAVE_LCHMOD]) ++ HAVE_LSTAT=1; AC_SUBST([HAVE_LSTAT]) ++ HAVE_MKDIRAT=1; AC_SUBST([HAVE_MKDIRAT]) ++ HAVE_MKFIFO=1; AC_SUBST([HAVE_MKFIFO]) ++ HAVE_MKFIFOAT=1; AC_SUBST([HAVE_MKFIFOAT]) ++ HAVE_MKNOD=1; AC_SUBST([HAVE_MKNOD]) ++ HAVE_MKNODAT=1; AC_SUBST([HAVE_MKNODAT]) ++ HAVE_UTIMENSAT=1; AC_SUBST([HAVE_UTIMENSAT]) ++ REPLACE_FSTAT=0; AC_SUBST([REPLACE_FSTAT]) ++ REPLACE_FSTATAT=0; AC_SUBST([REPLACE_FSTATAT]) ++ REPLACE_FUTIMENS=0; AC_SUBST([REPLACE_FUTIMENS]) ++ REPLACE_LSTAT=0; AC_SUBST([REPLACE_LSTAT]) ++ REPLACE_MKDIR=0; AC_SUBST([REPLACE_MKDIR]) ++ REPLACE_MKFIFO=0; AC_SUBST([REPLACE_MKFIFO]) ++ REPLACE_MKNOD=0; AC_SUBST([REPLACE_MKNOD]) ++ REPLACE_STAT=0; AC_SUBST([REPLACE_STAT]) ++ REPLACE_UTIMENSAT=0; AC_SUBST([REPLACE_UTIMENSAT]) ++]) +diff --git a/m4/sys_time_h.m4 b/m4/sys_time_h.m4 +new file mode 100644 +index 00000000000..5c79300f8ec +--- /dev/null ++++ b/m4/sys_time_h.m4 +@@ -0,0 +1,110 @@ ++# Configure a replacement for . ++# serial 8 ++ ++# Copyright (C) 2007, 2009-2014 Free Software Foundation, Inc. ++# This file is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. ++ ++# Written by Paul Eggert and Martin Lambers. ++ ++AC_DEFUN([gl_HEADER_SYS_TIME_H], ++[ ++ dnl Use AC_REQUIRE here, so that the REPLACE_GETTIMEOFDAY=0 statement ++ dnl below is expanded once only, before all REPLACE_GETTIMEOFDAY=1 ++ dnl statements that occur in other macros. ++ AC_REQUIRE([gl_HEADER_SYS_TIME_H_BODY]) ++]) ++ ++AC_DEFUN([gl_HEADER_SYS_TIME_H_BODY], ++[ ++ AC_REQUIRE([AC_C_RESTRICT]) ++ AC_REQUIRE([gl_HEADER_SYS_TIME_H_DEFAULTS]) ++ AC_CHECK_HEADERS_ONCE([sys/time.h]) ++ gl_CHECK_NEXT_HEADERS([sys/time.h]) ++ ++ if test $ac_cv_header_sys_time_h != yes; then ++ HAVE_SYS_TIME_H=0 ++ fi ++ ++ dnl On native Windows with MSVC, 'struct timeval' is defined in ++ dnl only. So include that header in the list. ++ gl_PREREQ_SYS_H_WINSOCK2 ++ AC_CACHE_CHECK([for struct timeval], [gl_cv_sys_struct_timeval], ++ [AC_COMPILE_IFELSE( ++ [AC_LANG_PROGRAM( ++ [[#if HAVE_SYS_TIME_H ++ #include ++ #endif ++ #include ++ #if HAVE_WINSOCK2_H ++ # include ++ #endif ++ ]], ++ [[static struct timeval x; x.tv_sec = x.tv_usec;]])], ++ [gl_cv_sys_struct_timeval=yes], ++ [gl_cv_sys_struct_timeval=no]) ++ ]) ++ if test $gl_cv_sys_struct_timeval != yes; then ++ HAVE_STRUCT_TIMEVAL=0 ++ else ++ dnl On native Windows with a 64-bit 'time_t', 'struct timeval' is defined ++ dnl (in and for mingw64, in only ++ dnl for MSVC) with a tv_sec field of type 'long' (32-bit!), which is ++ dnl smaller than the 'time_t' type mandated by POSIX. ++ dnl On OpenBSD 5.1 amd64, tv_sec is 64 bits and time_t 32 bits, but ++ dnl that is good enough. ++ AC_CACHE_CHECK([for wide-enough struct timeval.tv_sec member], ++ [gl_cv_sys_struct_timeval_tv_sec], ++ [AC_COMPILE_IFELSE( ++ [AC_LANG_PROGRAM( ++ [[#if HAVE_SYS_TIME_H ++ #include ++ #endif ++ #include ++ #if HAVE_WINSOCK2_H ++ # include ++ #endif ++ ]], ++ [[static struct timeval x; ++ typedef int verify_tv_sec_type[ ++ sizeof (time_t) <= sizeof x.tv_sec ? 1 : -1 ++ ]; ++ ]])], ++ [gl_cv_sys_struct_timeval_tv_sec=yes], ++ [gl_cv_sys_struct_timeval_tv_sec=no]) ++ ]) ++ if test $gl_cv_sys_struct_timeval_tv_sec != yes; then ++ REPLACE_STRUCT_TIMEVAL=1 ++ fi ++ fi ++ ++ dnl Check for declarations of anything we want to poison if the ++ dnl corresponding gnulib module is not in use. ++ gl_WARN_ON_USE_PREPARE([[ ++#if HAVE_SYS_TIME_H ++# include ++#endif ++#include ++ ]], [gettimeofday]) ++]) ++ ++AC_DEFUN([gl_SYS_TIME_MODULE_INDICATOR], ++[ ++ dnl Use AC_REQUIRE here, so that the default settings are expanded once only. ++ AC_REQUIRE([gl_HEADER_SYS_TIME_H_DEFAULTS]) ++ gl_MODULE_INDICATOR_SET_VARIABLE([$1]) ++ dnl Define it also as a C macro, for the benefit of the unit tests. ++ gl_MODULE_INDICATOR_FOR_TESTS([$1]) ++]) ++ ++AC_DEFUN([gl_HEADER_SYS_TIME_H_DEFAULTS], ++[ ++ GNULIB_GETTIMEOFDAY=0; AC_SUBST([GNULIB_GETTIMEOFDAY]) ++ dnl Assume POSIX behavior unless another module says otherwise. ++ HAVE_GETTIMEOFDAY=1; AC_SUBST([HAVE_GETTIMEOFDAY]) ++ HAVE_STRUCT_TIMEVAL=1; AC_SUBST([HAVE_STRUCT_TIMEVAL]) ++ HAVE_SYS_TIME_H=1; AC_SUBST([HAVE_SYS_TIME_H]) ++ REPLACE_GETTIMEOFDAY=0; AC_SUBST([REPLACE_GETTIMEOFDAY]) ++ REPLACE_STRUCT_TIMEVAL=0; AC_SUBST([REPLACE_STRUCT_TIMEVAL]) ++]) +diff --git a/m4/time_h.m4 b/m4/time_h.m4 +new file mode 100644 +index 00000000000..9852778f9a5 +--- /dev/null ++++ b/m4/time_h.m4 +@@ -0,0 +1,118 @@ ++# Configure a more-standard replacement for . ++ ++# Copyright (C) 2000-2001, 2003-2007, 2009-2014 Free Software Foundation, Inc. ++ ++# serial 8 ++ ++# This file is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. ++ ++# Written by Paul Eggert and Jim Meyering. ++ ++AC_DEFUN([gl_HEADER_TIME_H], ++[ ++ dnl Use AC_REQUIRE here, so that the default behavior below is expanded ++ dnl once only, before all statements that occur in other macros. ++ AC_REQUIRE([gl_HEADER_TIME_H_BODY]) ++]) ++ ++AC_DEFUN([gl_HEADER_TIME_H_BODY], ++[ ++ AC_REQUIRE([AC_C_RESTRICT]) ++ AC_REQUIRE([gl_HEADER_TIME_H_DEFAULTS]) ++ gl_NEXT_HEADERS([time.h]) ++ AC_REQUIRE([gl_CHECK_TYPE_STRUCT_TIMESPEC]) ++]) ++ ++dnl Check whether 'struct timespec' is declared ++dnl in time.h, sys/time.h, or pthread.h. ++ ++AC_DEFUN([gl_CHECK_TYPE_STRUCT_TIMESPEC], ++[ ++ AC_CHECK_HEADERS_ONCE([sys/time.h]) ++ AC_CACHE_CHECK([for struct timespec in ], ++ [gl_cv_sys_struct_timespec_in_time_h], ++ [AC_COMPILE_IFELSE( ++ [AC_LANG_PROGRAM( ++ [[#include ++ ]], ++ [[static struct timespec x; x.tv_sec = x.tv_nsec;]])], ++ [gl_cv_sys_struct_timespec_in_time_h=yes], ++ [gl_cv_sys_struct_timespec_in_time_h=no])]) ++ ++ TIME_H_DEFINES_STRUCT_TIMESPEC=0 ++ SYS_TIME_H_DEFINES_STRUCT_TIMESPEC=0 ++ PTHREAD_H_DEFINES_STRUCT_TIMESPEC=0 ++ if test $gl_cv_sys_struct_timespec_in_time_h = yes; then ++ TIME_H_DEFINES_STRUCT_TIMESPEC=1 ++ else ++ AC_CACHE_CHECK([for struct timespec in ], ++ [gl_cv_sys_struct_timespec_in_sys_time_h], ++ [AC_COMPILE_IFELSE( ++ [AC_LANG_PROGRAM( ++ [[#include ++ ]], ++ [[static struct timespec x; x.tv_sec = x.tv_nsec;]])], ++ [gl_cv_sys_struct_timespec_in_sys_time_h=yes], ++ [gl_cv_sys_struct_timespec_in_sys_time_h=no])]) ++ if test $gl_cv_sys_struct_timespec_in_sys_time_h = yes; then ++ SYS_TIME_H_DEFINES_STRUCT_TIMESPEC=1 ++ else ++ AC_CACHE_CHECK([for struct timespec in ], ++ [gl_cv_sys_struct_timespec_in_pthread_h], ++ [AC_COMPILE_IFELSE( ++ [AC_LANG_PROGRAM( ++ [[#include ++ ]], ++ [[static struct timespec x; x.tv_sec = x.tv_nsec;]])], ++ [gl_cv_sys_struct_timespec_in_pthread_h=yes], ++ [gl_cv_sys_struct_timespec_in_pthread_h=no])]) ++ if test $gl_cv_sys_struct_timespec_in_pthread_h = yes; then ++ PTHREAD_H_DEFINES_STRUCT_TIMESPEC=1 ++ fi ++ fi ++ fi ++ AC_SUBST([TIME_H_DEFINES_STRUCT_TIMESPEC]) ++ AC_SUBST([SYS_TIME_H_DEFINES_STRUCT_TIMESPEC]) ++ AC_SUBST([PTHREAD_H_DEFINES_STRUCT_TIMESPEC]) ++]) ++ ++AC_DEFUN([gl_TIME_MODULE_INDICATOR], ++[ ++ dnl Use AC_REQUIRE here, so that the default settings are expanded once only. ++ AC_REQUIRE([gl_HEADER_TIME_H_DEFAULTS]) ++ gl_MODULE_INDICATOR_SET_VARIABLE([$1]) ++ dnl Define it also as a C macro, for the benefit of the unit tests. ++ gl_MODULE_INDICATOR_FOR_TESTS([$1]) ++]) ++ ++AC_DEFUN([gl_HEADER_TIME_H_DEFAULTS], ++[ ++ GNULIB_MKTIME=0; AC_SUBST([GNULIB_MKTIME]) ++ GNULIB_NANOSLEEP=0; AC_SUBST([GNULIB_NANOSLEEP]) ++ GNULIB_STRPTIME=0; AC_SUBST([GNULIB_STRPTIME]) ++ GNULIB_TIMEGM=0; AC_SUBST([GNULIB_TIMEGM]) ++ GNULIB_TIME_R=0; AC_SUBST([GNULIB_TIME_R]) ++ dnl Assume proper GNU behavior unless another module says otherwise. ++ HAVE_DECL_LOCALTIME_R=1; AC_SUBST([HAVE_DECL_LOCALTIME_R]) ++ HAVE_NANOSLEEP=1; AC_SUBST([HAVE_NANOSLEEP]) ++ HAVE_STRPTIME=1; AC_SUBST([HAVE_STRPTIME]) ++ HAVE_TIMEGM=1; AC_SUBST([HAVE_TIMEGM]) ++ dnl If another module says to replace or to not replace, do that. ++ dnl Otherwise, replace only if someone compiles with -DGNULIB_PORTCHECK; ++ dnl this lets maintainers check for portability. ++ REPLACE_LOCALTIME_R=GNULIB_PORTCHECK; AC_SUBST([REPLACE_LOCALTIME_R]) ++ REPLACE_MKTIME=GNULIB_PORTCHECK; AC_SUBST([REPLACE_MKTIME]) ++ REPLACE_NANOSLEEP=GNULIB_PORTCHECK; AC_SUBST([REPLACE_NANOSLEEP]) ++ REPLACE_TIMEGM=GNULIB_PORTCHECK; AC_SUBST([REPLACE_TIMEGM]) ++ ++ dnl Hack so that the time module doesn't depend on the sys_time module. ++ dnl First, default GNULIB_GETTIMEOFDAY to 0 if sys_time is absent. ++ : ${GNULIB_GETTIMEOFDAY=0}; AC_SUBST([GNULIB_GETTIMEOFDAY]) ++ dnl Second, it's OK to not use GNULIB_PORTCHECK for REPLACE_GMTIME ++ dnl and REPLACE_LOCALTIME, as portability to Solaris 2.6 and earlier ++ dnl is no longer a big deal. ++ REPLACE_GMTIME=0; AC_SUBST([REPLACE_GMTIME]) ++ REPLACE_LOCALTIME=0; AC_SUBST([REPLACE_LOCALTIME]) ++]) diff --git a/SOURCES/0146-Make-editenv-chase-symlinks-including-those-across-d.patch b/SOURCES/0146-Make-editenv-chase-symlinks-including-those-across-d.patch new file mode 100644 index 0000000..a76154a --- /dev/null +++ b/SOURCES/0146-Make-editenv-chase-symlinks-including-those-across-d.patch @@ -0,0 +1,102 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 3 Sep 2014 10:38:00 -0400 +Subject: [PATCH] Make editenv chase symlinks including those across devices. + +This lets us make /boot/grub2/grubenv a symlink to +/boot/efi/EFI/fedora/grubenv even though they're different mount points, +which allows /usr/bin/grub2-editenv to be the same across platforms +(i.e. UEFI vs BIOS). + +Signed-off-by: Peter Jones +Reviewed-by: Adam Jackson +--- + Makefile.util.def | 9 +++++++++ + util/editenv.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- + 2 files changed, 53 insertions(+), 2 deletions(-) + +diff --git a/Makefile.util.def b/Makefile.util.def +index 8f40e78332a..87029a10dfb 100644 +--- a/Makefile.util.def ++++ b/Makefile.util.def +@@ -228,8 +228,17 @@ program = { + + common = util/grub-editenv.c; + common = util/editenv.c; ++ common = util/grub-install-common.c; + common = grub-core/osdep/init.c; ++ common = grub-core/osdep/compress.c; ++ extra_dist = grub-core/osdep/unix/compress.c; ++ extra_dist = grub-core/osdep/basic/compress.c; ++ common = util/mkimage.c; ++ common = grub-core/osdep/config.c; ++ common = util/config.c; ++ common = util/resolve.c; + ++ ldadd = '$(LIBLZMA)'; + ldadd = libgrubmods.a; + ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; +diff --git a/util/editenv.c b/util/editenv.c +index c6f8d2298c3..d8d1dad6ab9 100644 +--- a/util/editenv.c ++++ b/util/editenv.c +@@ -37,6 +37,7 @@ grub_util_create_envblk_file (const char *name) + FILE *fp; + char *buf; + char *namenew; ++ char *rename_target = xstrdup(name); + + buf = xmalloc (DEFAULT_ENVBLK_SIZE); + +@@ -59,7 +60,48 @@ grub_util_create_envblk_file (const char *name) + free (buf); + fclose (fp); + +- if (grub_util_rename (namenew, name) < 0) +- grub_util_error (_("cannot rename the file %s to %s"), namenew, name); ++ ssize_t size = 1; ++ while (1) ++ { ++ char *linkbuf; ++ ssize_t retsize; ++ ++ linkbuf = xmalloc(size+1); ++ retsize = grub_util_readlink (rename_target, linkbuf, size); ++ if (retsize < 0 && (errno == ENOENT || errno == EINVAL)) ++ { ++ free (linkbuf); ++ break; ++ } ++ else if (retsize < 0) ++ { ++ grub_util_error (_("cannot rename the file %s to %s: %m"), namenew, name); ++ free (linkbuf); ++ free (namenew); ++ return; ++ } ++ else if (retsize == size) ++ { ++ free(linkbuf); ++ size += 128; ++ continue; ++ } ++ ++ free (rename_target); ++ linkbuf[retsize] = '\0'; ++ rename_target = linkbuf; ++ } ++ ++ int rc = grub_util_rename (namenew, rename_target); ++ if (rc < 0 && errno == EXDEV) ++ { ++ rc = grub_install_copy_file (namenew, rename_target, 1); ++ grub_util_unlink (namenew); ++ } ++ ++ if (rc < 0) ++ grub_util_error (_("cannot rename the file %s to %s: %m"), namenew, name); ++ + free (namenew); ++ free (rename_target); + } diff --git a/SOURCES/0147-Generate-OS-and-CLASS-in-10_linux-from-etc-os-releas.patch b/SOURCES/0147-Generate-OS-and-CLASS-in-10_linux-from-etc-os-releas.patch new file mode 100644 index 0000000..e30aa62 --- /dev/null +++ b/SOURCES/0147-Generate-OS-and-CLASS-in-10_linux-from-etc-os-releas.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 4 Sep 2014 14:23:23 -0400 +Subject: [PATCH] Generate OS and CLASS in 10_linux from /etc/os-release + +This makes us use pretty names in the titles we generate in +grub2-mkconfig when GRUB_DISTRIBUTOR isn't set. + +Resolves: rhbz#996794 + +Signed-off-by: Peter Jones +--- + util/grub.d/10_linux.in | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index 8782d8c67cf..e8088a18160 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -29,7 +29,8 @@ export TEXTDOMAINDIR="@localedir@" + CLASS="--class gnu-linux --class gnu --class os --unrestricted" + + if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then +- OS="$(sed 's, release .*$,,g' /etc/system-release)" ++ OS="$(eval $(grep PRETTY_NAME /etc/os-release) ; echo ${PRETTY_NAME})" ++ CLASS="--class $(eval $(grep '^ID_LIKE=\|^ID=' /etc/os-release) ; [ -n "${ID_LIKE}" ] && echo ${ID_LIKE} || echo ${ID}) ${CLASS}" + else + OS="${GRUB_DISTRIBUTOR}" + CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1|LC_ALL=C sed 's,[^[:alnum:]_],_,g') ${CLASS}" diff --git a/SOURCES/0148-Minimize-the-sort-ordering-for-.debug-and-rescue-ker.patch b/SOURCES/0148-Minimize-the-sort-ordering-for-.debug-and-rescue-ker.patch new file mode 100644 index 0000000..717af81 --- /dev/null +++ b/SOURCES/0148-Minimize-the-sort-ordering-for-.debug-and-rescue-ker.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 4 Sep 2014 15:52:08 -0400 +Subject: [PATCH] Minimize the sort ordering for .debug and -rescue- kernels. + +Resolves: rhbz#1065360 +Signed-off-by: Peter Jones +--- + util/grub-mkconfig_lib.in | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in +index 14fadbcbbbd..7ac0bbed0d3 100644 +--- a/util/grub-mkconfig_lib.in ++++ b/util/grub-mkconfig_lib.in +@@ -248,6 +248,14 @@ version_test_gt () + *.old:*.old) ;; + *.old:*) version_test_gt_a="`echo -n "$version_test_gt_a" | sed -e 's/\.old$//'`" ; version_test_gt_cmp=gt ;; + *:*.old) version_test_gt_b="`echo -n "$version_test_gt_b" | sed -e 's/\.old$//'`" ; version_test_gt_cmp=ge ;; ++ *-rescue-*:*-rescue-*) ;; ++ *.debug:*.debug) ;; ++ *-rescue-*:*.debug) return 1 ;; ++ *.debug:*-rescue-*) return 0 ;; ++ *-rescue-*:*) return 1 ;; ++ *:*-rescue-*) return 0 ;; ++ *.debug:*) return 1 ;; ++ *:*.debug) return 0 ;; + esac + version_test_numeric "$version_test_gt_a" "$version_test_gt_cmp" "$version_test_gt_b" + return "$?" diff --git a/SOURCES/0149-Add-GRUB_DISABLE_UUID.patch b/SOURCES/0149-Add-GRUB_DISABLE_UUID.patch new file mode 100644 index 0000000..7804329 --- /dev/null +++ b/SOURCES/0149-Add-GRUB_DISABLE_UUID.patch @@ -0,0 +1,99 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 4 Sep 2014 16:49:25 -0400 +Subject: [PATCH] Add GRUB_DISABLE_UUID. + +This will cause "search --fs-uuid --set=root ..." not to be generated by +grub2-mkconfig, and instead simply attempt to use the grub device name +as it understands it. + +Good luck. + +Resolves: rhbz#1027833 +Signed-off-by: Peter Jones +--- + docs/grub.texi | 7 +++++++ + util/grub-mkconfig.in | 12 ++++++++++-- + util/grub-mkconfig_lib.in | 4 ++-- + 3 files changed, 19 insertions(+), 4 deletions(-) + +diff --git a/docs/grub.texi b/docs/grub.texi +index 46b9e7f8e31..6b112c18804 100644 +--- a/docs/grub.texi ++++ b/docs/grub.texi +@@ -1409,6 +1409,13 @@ disable the use of UUIDs, set this option to @samp{true}. + If this option is set to @samp{true}, disable the generation of recovery + mode menu entries. + ++@item GRUB_DISABLE_UUID ++Normally, @command{grub-mkconfig} will generate menu entries that use ++universally-unique identifiers (UUIDs) to identify various filesystems to ++search for files. This is usually more reliable, but in some cases it may ++not be appropriate. To disable this use of UUIDs, set this option to ++@samp{true}. ++ + @item GRUB_VIDEO_BACKEND + If graphical video support is required, either because the @samp{gfxterm} + graphical terminal is in use or because @samp{GRUB_GFXPAYLOAD_LINUX} is set, +diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in +index beb22deee79..bc26e7c109e 100644 +--- a/util/grub-mkconfig.in ++++ b/util/grub-mkconfig.in +@@ -130,11 +130,11 @@ fi + + # Device containing our userland. Typically used for root= parameter. + GRUB_DEVICE="`${grub_probe} --target=device /`" +-GRUB_DEVICE_UUID="`${grub_probe} --device ${GRUB_DEVICE} --target=fs_uuid 2> /dev/null`" || true ++GRUB_DEVICE_UUID_GENERATED="`${grub_probe} --device ${GRUB_DEVICE} --target=fs_uuid 2> /dev/null`" || true + + # Device containing our /boot partition. Usually the same as GRUB_DEVICE. + GRUB_DEVICE_BOOT="`${grub_probe} --target=device /boot`" +-GRUB_DEVICE_BOOT_UUID="`${grub_probe} --device ${GRUB_DEVICE_BOOT} --target=fs_uuid 2> /dev/null`" || true ++GRUB_DEVICE_BOOT_UUID_GENERATED="`${grub_probe} --device ${GRUB_DEVICE_BOOT} --target=fs_uuid 2> /dev/null`" || true + + # Filesystem for the device containing our userland. Used for stuff like + # choosing Hurd filesystem module. +@@ -148,6 +148,13 @@ if test -f ${sysconfdir}/default/grub ; then + . ${sysconfdir}/default/grub + fi + ++if [ "x$GRUB_DISABLE_UUID" != "xtrue" -a -z "$GRUB_DEVICE_UUID" ]; then ++ GRUB_DEVICE_UUID="$GRUB_DEVICE_UUID_GENERATED" ++fi ++if [ "x$GRUB_DISABLE_UUID" != "xtrue" -a -z "$GRUB_DEVICE_BOOT_UUID" ]; then ++ GRUB_DEVICE_BOOT_UUID="$GRUB_DEVICE_BOOT_UUID_GENERATED" ++fi ++ + # XXX: should this be deprecated at some point? + if [ "x${GRUB_TERMINAL}" != "x" ] ; then + GRUB_TERMINAL_INPUT="${GRUB_TERMINAL}" +@@ -213,6 +220,7 @@ export GRUB_DEFAULT \ + GRUB_SERIAL_COMMAND \ + GRUB_DISABLE_LINUX_UUID \ + GRUB_DISABLE_RECOVERY \ ++ GRUB_DISABLE_UUID \ + GRUB_VIDEO_BACKEND \ + GRUB_GFXMODE \ + GRUB_BACKGROUND \ +diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in +index 7ac0bbed0d3..5c9ed84a5e7 100644 +--- a/util/grub-mkconfig_lib.in ++++ b/util/grub-mkconfig_lib.in +@@ -156,7 +156,7 @@ prepare_grub_to_access_device () + if [ "x$fs_hint" != x ]; then + echo "set root='$fs_hint'" + fi +- if fs_uuid="`"${grub_probe}" --device $@ --target=fs_uuid 2> /dev/null`" ; then ++ if [ "x$GRUB_DISABLE_UUID" != "xtrue" ] && fs_uuid="`"${grub_probe}" --device $@ --target=fs_uuid 2> /dev/null`" ; then + hints="`"${grub_probe}" --device $@ --target=hints_string 2> /dev/null`" || hints= + echo "if [ x\$feature_platform_search_hint = xy ]; then" + echo " search --no-floppy --fs-uuid --set=root ${hints} ${fs_uuid}" +@@ -173,7 +173,7 @@ grub_get_device_id () + IFS=' + ' + device="$1" +- if fs_uuid="`"${grub_probe}" --device ${device} --target=fs_uuid 2> /dev/null`" ; then ++ if [ "x$GRUB_DISABLE_UUID" != "xtrue" ] && fs_uuid="`"${grub_probe}" --device ${device} --target=fs_uuid 2> /dev/null`" ; then + echo "$fs_uuid"; + else + echo $device |sed 's, ,_,g' diff --git a/SOURCES/0150-Allow-fallback-to-include-entries-by-title-not-just-.patch b/SOURCES/0150-Allow-fallback-to-include-entries-by-title-not-just-.patch new file mode 100644 index 0000000..be4c654 --- /dev/null +++ b/SOURCES/0150-Allow-fallback-to-include-entries-by-title-not-just-.patch @@ -0,0 +1,128 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 5 Sep 2014 10:07:04 -0400 +Subject: [PATCH] Allow "fallback" to include entries by title, not just + number. + +Resolves: rhbz#1026084 + +Signed-off-by: Peter Jones +--- + grub-core/normal/menu.c | 76 +++++++++++++++++++++++++++++++------------------ + 1 file changed, 49 insertions(+), 27 deletions(-) + +diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c +index cc27c370776..a446d9ae746 100644 +--- a/grub-core/normal/menu.c ++++ b/grub-core/normal/menu.c +@@ -163,12 +163,35 @@ grub_menu_set_timeout (int timeout) + } + } + ++static int ++menuentry_eq (const char *id, const char *spec) ++{ ++ const char *ptr1, *ptr2; ++ ptr1 = id; ++ ptr2 = spec; ++ while (1) ++ { ++ if (*ptr2 == '>' && ptr2[1] != '>' && *ptr1 == 0) ++ return 1; ++ if (*ptr2 == '>' && ptr2[1] != '>') ++ return 0; ++ if (*ptr2 == '>') ++ ptr2++; ++ if (*ptr1 != *ptr2) ++ return 0; ++ if (*ptr1 == 0) ++ return 1; ++ ptr1++; ++ ptr2++; ++ } ++} ++ + /* Get the first entry number from the value of the environment variable NAME, + which is a space-separated list of non-negative integers. The entry number + which is returned is stripped from the value of NAME. If no entry number + can be found, -1 is returned. */ + static int +-get_and_remove_first_entry_number (const char *name) ++get_and_remove_first_entry_number (grub_menu_t menu, const char *name) + { + const char *val; + char *tail; +@@ -182,9 +205,32 @@ get_and_remove_first_entry_number (const char *name) + + entry = (int) grub_strtoul (val, &tail, 0); + ++ if (grub_errno == GRUB_ERR_BAD_NUMBER) ++ { ++ /* See if the variable matches the title of a menu entry. */ ++ grub_menu_entry_t e = menu->entry_list; ++ int i; ++ ++ grub_errno = GRUB_ERR_NONE; ++ ++ for (i = 0; e; i++) ++ { ++ if (menuentry_eq (e->title, val) ++ || menuentry_eq (e->id, val)) ++ { ++ entry = i; ++ break; ++ } ++ e = e->next; ++ } ++ ++ if (! e) ++ entry = -1; ++ } ++ + if (grub_errno == GRUB_ERR_NONE) + { +- /* Skip whitespace to find the next digit. */ ++ /* Skip whitespace to find the next entry. */ + while (*tail && grub_isspace (*tail)) + tail++; + grub_env_set (name, tail); +@@ -347,7 +393,7 @@ grub_menu_execute_with_fallback (grub_menu_t menu, + grub_menu_execute_entry (entry, 1); + + /* Deal with fallback entries. */ +- while ((fallback_entry = get_and_remove_first_entry_number ("fallback")) ++ while ((fallback_entry = get_and_remove_first_entry_number (menu, "fallback")) + >= 0) + { + grub_print_error (); +@@ -465,30 +511,6 @@ grub_menu_register_viewer (struct grub_menu_viewer *viewer) + viewers = viewer; + } + +-static int +-menuentry_eq (const char *id, const char *spec) +-{ +- const char *ptr1, *ptr2; +- ptr1 = id; +- ptr2 = spec; +- while (1) +- { +- if (*ptr2 == '>' && ptr2[1] != '>' && *ptr1 == 0) +- return 1; +- if (*ptr2 == '>' && ptr2[1] != '>') +- return 0; +- if (*ptr2 == '>') +- ptr2++; +- if (*ptr1 != *ptr2) +- return 0; +- if (*ptr1 == 0) +- return 1; +- ptr1++; +- ptr2++; +- } +-} +- +- + /* Get the entry number from the variable NAME. */ + static int + get_entry_number (grub_menu_t menu, const char *name) diff --git a/SOURCES/0151-Initialized-initrd_ctx-so-we-don-t-free-a-random-poi.patch b/SOURCES/0151-Initialized-initrd_ctx-so-we-don-t-free-a-random-poi.patch new file mode 100644 index 0000000..da73645 --- /dev/null +++ b/SOURCES/0151-Initialized-initrd_ctx-so-we-don-t-free-a-random-poi.patch @@ -0,0 +1,131 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 17 Sep 2014 15:13:14 -0500 +Subject: [PATCH] Initialized initrd_ctx so we don't free a random pointer from + the stack. + +Currently, if "linux" fails, the "goto fail;" in grub_cmd_initrd sends us +into grub_initrd_close() without grub_initrd_init() being called, and thus +it never clears initrd_ctx->components. grub_initrd_close() then frees that +address, which is stale data from the stack. If the stack happens to have a +stale *address* there that matches a recent allocation, then you'll get a +double free later. + +So initialize the memory up front. + +Signed-off-by: Peter Jones +--- + grub-core/loader/arm/linux.c | 2 +- + grub-core/loader/arm64/linux.c | 2 +- + grub-core/loader/i386/linux.c | 2 +- + grub-core/loader/i386/pc/linux.c | 2 +- + grub-core/loader/ia64/efi/linux.c | 2 +- + grub-core/loader/mips/linux.c | 2 +- + grub-core/loader/powerpc/ieee1275/linux.c | 2 +- + grub-core/loader/sparc64/ieee1275/linux.c | 2 +- + 8 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/grub-core/loader/arm/linux.c b/grub-core/loader/arm/linux.c +index e6770d96d29..62cbe75d34e 100644 +--- a/grub-core/loader/arm/linux.c ++++ b/grub-core/loader/arm/linux.c +@@ -396,7 +396,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + { + grub_file_t file; + grub_size_t size = 0; +- struct grub_linux_initrd_context initrd_ctx; ++ struct grub_linux_initrd_context initrd_ctx = { 0, }; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); +diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c +index f1d10a16492..0dc144e5da0 100644 +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -328,7 +328,7 @@ static grub_err_t + grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) + { +- struct grub_linux_initrd_context initrd_ctx; ++ struct grub_linux_initrd_context initrd_ctx = { 0, }; + int initrd_size, initrd_pages; + void *initrd_mem = NULL; + +diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c +index 31fb91e2c73..2ae176315b6 100644 +--- a/grub-core/loader/i386/linux.c ++++ b/grub-core/loader/i386/linux.c +@@ -1050,7 +1050,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + grub_addr_t addr_min, addr_max; + grub_addr_t addr; + grub_err_t err; +- struct grub_linux_initrd_context initrd_ctx; ++ struct grub_linux_initrd_context initrd_ctx = { 0, }; + + if (argc == 0) + { +diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c +index 672c013e74d..b481e466846 100644 +--- a/grub-core/loader/i386/pc/linux.c ++++ b/grub-core/loader/i386/pc/linux.c +@@ -388,7 +388,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + grub_uint8_t *initrd_chunk; + grub_addr_t initrd_addr; + grub_err_t err; +- struct grub_linux_initrd_context initrd_ctx; ++ struct grub_linux_initrd_context initrd_ctx = { 0, }; + + if (argc == 0) + { +diff --git a/grub-core/loader/ia64/efi/linux.c b/grub-core/loader/ia64/efi/linux.c +index 87ac49f8c3b..eb78e6e626b 100644 +--- a/grub-core/loader/ia64/efi/linux.c ++++ b/grub-core/loader/ia64/efi/linux.c +@@ -568,7 +568,7 @@ static grub_err_t + grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) + { +- struct grub_linux_initrd_context initrd_ctx; ++ struct grub_linux_initrd_context initrd_ctx = { 0, }; + + if (argc == 0) + { +diff --git a/grub-core/loader/mips/linux.c b/grub-core/loader/mips/linux.c +index ef64a5b1d36..4a3e8c5dfa2 100644 +--- a/grub-core/loader/mips/linux.c ++++ b/grub-core/loader/mips/linux.c +@@ -415,7 +415,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + void *initrd_src; + grub_addr_t initrd_dest; + grub_err_t err; +- struct grub_linux_initrd_context initrd_ctx; ++ struct grub_linux_initrd_context initrd_ctx = { 0, }; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); +diff --git a/grub-core/loader/powerpc/ieee1275/linux.c b/grub-core/loader/powerpc/ieee1275/linux.c +index 4a14f66dee5..787d7dc2af3 100644 +--- a/grub-core/loader/powerpc/ieee1275/linux.c ++++ b/grub-core/loader/powerpc/ieee1275/linux.c +@@ -333,7 +333,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + grub_size_t size = 0; + grub_addr_t first_addr; + grub_addr_t addr; +- struct grub_linux_initrd_context initrd_ctx; ++ struct grub_linux_initrd_context initrd_ctx = { 0, }; + + if (argc == 0) + { +diff --git a/grub-core/loader/sparc64/ieee1275/linux.c b/grub-core/loader/sparc64/ieee1275/linux.c +index de6ee2f75ed..c5e8dfab234 100644 +--- a/grub-core/loader/sparc64/ieee1275/linux.c ++++ b/grub-core/loader/sparc64/ieee1275/linux.c +@@ -373,7 +373,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + grub_addr_t paddr; + grub_addr_t addr; + int ret; +- struct grub_linux_initrd_context initrd_ctx; ++ struct grub_linux_initrd_context initrd_ctx = { 0, }; + + if (argc == 0) + { diff --git a/SOURCES/0152-Load-arm-with-SB-enabled.patch b/SOURCES/0152-Load-arm-with-SB-enabled.patch new file mode 100644 index 0000000..cc0fa4c --- /dev/null +++ b/SOURCES/0152-Load-arm-with-SB-enabled.patch @@ -0,0 +1,433 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 18 Sep 2014 11:26:14 -0400 +Subject: [PATCH] Load arm with SB enabled. + +Make sure we actually try to validate secure boot on this platform (even +though we're not shipping it enabled by default.) + +This means giving the kernel grub's loaded image as the vehicle for the +kernel command line, because we can't call systab->bs->LoadImage() if SB +is enabled. +--- + grub-core/Makefile.core.def | 2 + + grub-core/loader/arm64/linux.c | 108 ++++++++++++++++++++------------------ + grub-core/loader/efi/linux.c | 65 +++++++++++++++++++++++ + grub-core/loader/i386/efi/linux.c | 39 ++------------ + include/grub/arm64/linux.h | 8 +++ + include/grub/efi/linux.h | 31 +++++++++++ + 6 files changed, 166 insertions(+), 87 deletions(-) + create mode 100644 grub-core/loader/efi/linux.c + create mode 100644 include/grub/efi/linux.h + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 9ff9ae5a311..9378c732981 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -1682,6 +1682,7 @@ module = { + ia64_efi = loader/ia64/efi/linux.c; + arm = loader/arm/linux.c; + arm64 = loader/arm64/linux.c; ++ arm64 = loader/efi/linux.c; + fdt = lib/fdt.c; + common = loader/linux.c; + common = lib/cmdline.c; +@@ -1718,6 +1719,7 @@ module = { + name = linuxefi; + efi = loader/i386/efi/linux.c; + efi = lib/cmdline.c; ++ efi = loader/efi/linux.c; + enable = i386_efi; + enable = x86_64_efi; + }; +diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c +index 0dc144e5da0..bdd9c9b4968 100644 +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -44,6 +45,7 @@ static int loaded; + + static void *kernel_addr; + static grub_uint64_t kernel_size; ++static grub_uint32_t handover_offset; + + static char *linux_args; + static grub_uint32_t cmdline_size; +@@ -135,7 +137,9 @@ finalize_params (void) + { + grub_efi_boot_services_t *b; + grub_efi_status_t status; ++ grub_efi_loaded_image_t *loaded_image = NULL; + int node, retval; ++ int len; + + get_fdt (); + if (!fdt) +@@ -172,6 +176,23 @@ finalize_params (void) + grub_dprintf ("linux", "Installed/updated FDT configuration table @ %p\n", + fdt); + ++ /* Convert command line to UCS-2 */ ++ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle); ++ if (!loaded_image) ++ goto failure; ++ ++ loaded_image->load_options_size = len = ++ (grub_strlen (linux_args) + 1) * sizeof (grub_efi_char16_t); ++ loaded_image->load_options = ++ grub_efi_allocate_pages (0, ++ BYTES_TO_PAGES (loaded_image->load_options_size)); ++ if (!loaded_image->load_options) ++ return grub_error(GRUB_ERR_BAD_OS, "failed to create kernel parameters"); ++ ++ loaded_image->load_options_size = ++ 2 * grub_utf8_to_utf16 (loaded_image->load_options, len, ++ (grub_uint8_t *) linux_args, len, NULL); ++ + return GRUB_ERR_NONE; + + failure: +@@ -181,6 +202,23 @@ failure: + return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT"); + } + ++static void ++free_params (void) ++{ ++ grub_efi_loaded_image_t *loaded_image = NULL; ++ ++ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle); ++ if (loaded_image) ++ { ++ if (loaded_image->load_options) ++ grub_efi_free_pages ((grub_efi_physical_address_t) ++ loaded_image->load_options, ++ BYTES_TO_PAGES (loaded_image->load_options_size)); ++ loaded_image->load_options = NULL; ++ loaded_image->load_options_size = 0; ++ } ++} ++ + static grub_err_t + grub_cmd_devicetree (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) +@@ -199,6 +237,10 @@ grub_cmd_devicetree (grub_command_t cmd __attribute__ ((unused)), + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); + ++ if (grub_efi_secure_boot ()) ++ return grub_error (GRUB_ERR_INVALID_COMMAND, ++ N_("Not loading devicetree - Secure Boot is enabled")); ++ + if (loaded_fdt) + grub_free (loaded_fdt); + loaded_fdt = NULL; +@@ -243,65 +285,20 @@ out: + static grub_err_t + grub_linux_boot (void) + { +- grub_efi_memory_mapped_device_path_t *mempath; +- grub_efi_handle_t image_handle; +- grub_efi_boot_services_t *b; +- grub_efi_status_t status; + grub_err_t retval; +- grub_efi_loaded_image_t *loaded_image; +- int len; + + retval = finalize_params(); + if (retval != GRUB_ERR_NONE) + return retval; + +- mempath = grub_malloc (2 * sizeof (grub_efi_memory_mapped_device_path_t)); +- if (!mempath) +- return grub_errno; +- +- mempath[0].header.type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE; +- mempath[0].header.subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE; +- mempath[0].header.length = grub_cpu_to_le16_compile_time (sizeof (*mempath)); +- mempath[0].memory_type = GRUB_EFI_LOADER_DATA; +- mempath[0].start_address = (grub_addr_t) kernel_addr; +- mempath[0].end_address = (grub_addr_t) kernel_addr + kernel_size; +- +- mempath[1].header.type = GRUB_EFI_END_DEVICE_PATH_TYPE; +- mempath[1].header.subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; +- mempath[1].header.length = sizeof (grub_efi_device_path_t); +- +- b = grub_efi_system_table->boot_services; +- status = b->load_image (0, grub_efi_image_handle, +- (grub_efi_device_path_t *) mempath, +- kernel_addr, kernel_size, &image_handle); +- if (status != GRUB_EFI_SUCCESS) +- return grub_error (GRUB_ERR_BAD_OS, "cannot load image"); +- + grub_dprintf ("linux", "linux command line: '%s'\n", linux_args); + +- /* Convert command line to UCS-2 */ +- loaded_image = grub_efi_get_loaded_image (image_handle); +- loaded_image->load_options_size = len = +- (grub_strlen (linux_args) + 1) * sizeof (grub_efi_char16_t); +- loaded_image->load_options = +- grub_efi_allocate_pages (0, +- BYTES_TO_PAGES (loaded_image->load_options_size)); +- if (!loaded_image->load_options) +- return grub_errno; ++ retval = grub_efi_linux_boot ((char *)kernel_addr, handover_offset, ++ kernel_addr); + +- loaded_image->load_options_size = +- 2 * grub_utf8_to_utf16 (loaded_image->load_options, len, +- (grub_uint8_t *) linux_args, len, NULL); +- +- grub_dprintf("linux", "starting image %p\n", image_handle); +- status = b->start_image (image_handle, 0, NULL); +- +- /* When successful, not reached */ +- b->unload_image (image_handle); +- grub_efi_free_pages ((grub_efi_physical_address_t) loaded_image->load_options, +- BYTES_TO_PAGES (loaded_image->load_options_size)); +- +- return grub_errno; ++ /* Never reached... */ ++ free_params(); ++ return retval; + } + + static grub_err_t +@@ -382,6 +379,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + { + grub_file_t file = 0; + struct grub_arm64_linux_kernel_header lh; ++ struct grub_arm64_linux_pe_header *pe; + + grub_dl_ref (my_mod); + +@@ -426,6 +424,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + + grub_dprintf ("linux", "kernel @ %p\n", kernel_addr); + ++ if (!grub_linuxefi_secure_validate (kernel_addr, kernel_size)) ++ { ++ grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]); ++ goto fail; ++ } ++ ++ pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset); ++ handover_offset = pe->opt.entry_addr; ++ + cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE); + linux_args = grub_malloc (cmdline_size); + if (!linux_args) +@@ -464,7 +471,6 @@ fail: + return grub_errno; + } + +- + static grub_command_t cmd_linux, cmd_initrd, cmd_devicetree; + + GRUB_MOD_INIT (linux) +diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c +new file mode 100644 +index 00000000000..aea378adf5c +--- /dev/null ++++ b/grub-core/loader/efi/linux.c +@@ -0,0 +1,65 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2014 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define SHIM_LOCK_GUID \ ++ { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} } ++ ++struct grub_efi_shim_lock ++{ ++ grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size); ++}; ++typedef struct grub_efi_shim_lock grub_efi_shim_lock_t; ++ ++grub_efi_boolean_t ++grub_linuxefi_secure_validate (void *data, grub_uint32_t size) ++{ ++ grub_efi_guid_t guid = SHIM_LOCK_GUID; ++ grub_efi_shim_lock_t *shim_lock; ++ ++ shim_lock = grub_efi_locate_protocol(&guid, NULL); ++ ++ if (!shim_lock) ++ return 1; ++ ++ if (shim_lock->verify(data, size) == GRUB_EFI_SUCCESS) ++ return 1; ++ ++ return 0; ++} ++ ++typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *); ++ ++grub_err_t ++grub_efi_linux_boot (void *kernel_addr, grub_off_t offset, ++ void *kernel_params) ++{ ++ handover_func hf; ++ ++ hf = (handover_func)((char *)kernel_addr + offset); ++ hf (grub_efi_image_handle, grub_efi_system_table, kernel_params); ++ ++ return GRUB_ERR_BUG; ++} +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index b79e6320ba9..e5b778577f9 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -40,52 +41,18 @@ static char *linux_cmdline; + + #define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12) + +-#define SHIM_LOCK_GUID \ +- { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} } +- +-struct grub_efi_shim_lock +-{ +- grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size); +-}; +-typedef struct grub_efi_shim_lock grub_efi_shim_lock_t; +- +-static grub_efi_boolean_t +-grub_linuxefi_secure_validate (void *data, grub_uint32_t size) +-{ +- grub_efi_guid_t guid = SHIM_LOCK_GUID; +- grub_efi_shim_lock_t *shim_lock; +- +- shim_lock = grub_efi_locate_protocol(&guid, NULL); +- +- if (!shim_lock) +- return 1; +- +- if (shim_lock->verify(data, size) == GRUB_EFI_SUCCESS) +- return 1; +- +- return 0; +-} +- +-typedef void(*handover_func)(void *, grub_efi_system_table_t *, struct linux_kernel_params *); +- + static grub_err_t + grub_linuxefi_boot (void) + { +- handover_func hf; + int offset = 0; + + #ifdef __x86_64__ + offset = 512; + #endif +- +- hf = (handover_func)((char *)kernel_mem + handover_offset + offset); +- + asm volatile ("cli"); + +- hf (grub_efi_image_handle, grub_efi_system_table, params); +- +- /* Not reached */ +- return GRUB_ERR_NONE; ++ return grub_efi_linux_boot ((char *)kernel_mem, handover_offset + offset, ++ params); + } + + static grub_err_t +diff --git a/include/grub/arm64/linux.h b/include/grub/arm64/linux.h +index 864e5dc363a..2cbd64f8c55 100644 +--- a/include/grub/arm64/linux.h ++++ b/include/grub/arm64/linux.h +@@ -20,6 +20,7 @@ + #define GRUB_LINUX_CPU_HEADER 1 + + #include ++#include + + #define GRUB_ARM64_LINUX_MAGIC 0x644d5241 /* 'ARM\x64' */ + +@@ -38,4 +39,11 @@ struct grub_arm64_linux_kernel_header + grub_uint32_t hdr_offset; /* Offset of PE/COFF header */ + }; + ++struct grub_arm64_linux_pe_header ++{ ++ grub_uint32_t magic; ++ struct grub_pe32_coff_header coff; ++ struct grub_pe64_optional_header opt; ++}; ++ + #endif /* ! GRUB_LINUX_CPU_HEADER */ +diff --git a/include/grub/efi/linux.h b/include/grub/efi/linux.h +new file mode 100644 +index 00000000000..d9ede36773b +--- /dev/null ++++ b/include/grub/efi/linux.h +@@ -0,0 +1,31 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2014 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++#ifndef GRUB_EFI_LINUX_HEADER ++#define GRUB_EFI_LINUX_HEADER 1 ++ ++#include ++#include ++#include ++ ++grub_efi_boolean_t ++EXPORT_FUNC(grub_linuxefi_secure_validate) (void *data, grub_uint32_t size); ++grub_err_t ++EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset, ++ void *kernel_param); ++ ++#endif /* ! GRUB_EFI_LINUX_HEADER */ diff --git a/SOURCES/0153-Fix-up-some-man-pages-rpmdiff-noticed.patch b/SOURCES/0153-Fix-up-some-man-pages-rpmdiff-noticed.patch new file mode 100644 index 0000000..258a63f --- /dev/null +++ b/SOURCES/0153-Fix-up-some-man-pages-rpmdiff-noticed.patch @@ -0,0 +1,150 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 23 Sep 2014 09:58:49 -0400 +Subject: [PATCH] Fix up some man pages rpmdiff noticed. + +--- + configure.ac | 2 ++ + util/grub-macbless.8 | 26 +++++++++++++++++++ + util/grub-mkimage.1 | 2 +- + util/grub-syslinux2cfg.1 | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 94 insertions(+), 1 deletion(-) + create mode 100644 util/grub-macbless.8 + create mode 100644 util/grub-syslinux2cfg.1 + +diff --git a/configure.ac b/configure.ac +index 53fd7c73ee6..048ce7c89fa 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -76,6 +76,7 @@ grub_TRANSFORM([grub-fstest.3]) + grub_TRANSFORM([grub-glue-efi.3]) + grub_TRANSFORM([grub-install.1]) + grub_TRANSFORM([grub-kbdcomp.3]) ++grub_TRANSFORM([grub-macbless.8]) + grub_TRANSFORM([grub-menulst2cfg.1]) + grub_TRANSFORM([grub-mkconfig.1]) + grub_TRANSFORM([grub-mkfont.3]) +@@ -93,6 +94,7 @@ grub_TRANSFORM([grub-render-label.3]) + grub_TRANSFORM([grub-script-check.3]) + grub_TRANSFORM([grub-set-default.1]) + grub_TRANSFORM([grub-sparc64-setup.3]) ++grub_TRANSFORM([grub-syslinux2cfg.1]) + + # Optimization flag. Allow user to override. + if test "x$TARGET_CFLAGS" = x; then +diff --git a/util/grub-macbless.8 b/util/grub-macbless.8 +new file mode 100644 +index 00000000000..ae842f3a606 +--- /dev/null ++++ b/util/grub-macbless.8 +@@ -0,0 +1,26 @@ ++.TH GRUB-MACBLESS 1 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-macbless\fR \(em Mac-style bless utility for HFS or HFS+ ++ ++.SH SYNOPSIS ++\fBgrub-macbless\fR [-p | --ppc] [-v | --verbose] [-x | --x86] \fIFILE\fR ++ ++.SH DESCRIPTION ++\fBgrub-mkimage\fR blesses a file on an HFS or HFS+ file system, so that it ++can be used to boot a Mac. ++ ++.SH OPTIONS ++.TP ++--ppc ++Bless the file for use on PPC-based Macs. ++ ++.TP ++--verbose ++Print verbose messages. ++ ++.TP ++--x86 ++Bless the file for use on x86-based Macs. ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-mkimage.1 b/util/grub-mkimage.1 +index 4dea4f54597..0eaaafe505b 100644 +--- a/util/grub-mkimage.1 ++++ b/util/grub-mkimage.1 +@@ -17,7 +17,7 @@ + [-v | --verbose] \fIMODULES\fR + + .SH DESCRIPTION +-\fBgrub-mkimage\fI builds a bootable image of GRUB. ++\fBgrub-mkimage\fR builds a bootable image of GRUB. + + .SH OPTIONS + .TP +diff --git a/util/grub-syslinux2cfg.1 b/util/grub-syslinux2cfg.1 +new file mode 100644 +index 00000000000..85309482718 +--- /dev/null ++++ b/util/grub-syslinux2cfg.1 +@@ -0,0 +1,65 @@ ++.TH GRUB-SYSLINUX2CFG 1 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-syslinux2cfg\fR \(em Transform a syslinux config file into a GRUB config. ++ ++.SH SYNOPSIS ++\fBgrub-syslinux2cfg\fR [-c | --cwd=\fRDIR\fI] [-r | --root=\fIDIR\fR] [-v | --verbose] ++.RE ++.RS 25 ++[-t | --target-root=\fIDIR\fR] [-T | --target-cwd=\fIDIR\fR] ++.RE ++.RS 25 ++[-o | --output=\fIFILE\fR] [[-i | --isolinux] | ++.RE ++.RS 46 ++ [-s | --syslinux] | ++.RE ++.RS 46 ++ [-p | --pxelinux]] \fIFILE\fR ++ ++.SH DESCRIPTION ++\fBgrub-syslinux2cfg\fR builds a GRUB configuration file out of an existing ++syslinux configuration file. ++ ++.SH OPTIONS ++.TP ++--cwd=\fIDIR\fR ++Set \fIDIR\fR as syslinux's working directory. The default is to use the ++parent directory of the input file. ++ ++.TP ++--root=\fIDIR\fR ++Set \fIDIR\fR as the root directory of the syslinux disk. The default value ++is "/". ++ ++.TP ++--verbose ++Print verbose messages. ++ ++.TP ++--target-root=\fIDIR\fR ++Root directory as it will be seen at runtime. The default value is "/". ++ ++.TP ++--target-cwd=\fIDIR\fR ++Working directory of syslinux as it will be seen at runtime. The default ++value is the parent directory of the input file. ++ ++.TP ++--output=\fIFILE\fR ++Write the new config file to \fIFILE\fR. The default value is standard output. ++ ++.TP ++--isolinux ++Assume that the input file is an isolinux configuration file. ++ ++.TP ++--pxelinux ++Assume that the input file is a pxelinux configuration file. ++ ++.TP ++--syslinux ++Assume that the input file is a syslinux configuration file. ++ ++.SH SEE ALSO ++.BR "info grub" diff --git a/SOURCES/0154-Try-prefix-if-fw_path-doesn-t-work.patch b/SOURCES/0154-Try-prefix-if-fw_path-doesn-t-work.patch new file mode 100644 index 0000000..5a99a8e --- /dev/null +++ b/SOURCES/0154-Try-prefix-if-fw_path-doesn-t-work.patch @@ -0,0 +1,208 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 3 Oct 2014 11:08:03 -0400 +Subject: [PATCH] Try $prefix if $fw_path doesn't work. + +Related: rhbz#1148652 + +Signed-off-by: Peter Jones +--- + grub-core/kern/ieee1275/init.c | 28 +++++----- + grub-core/net/net.c | 2 +- + grub-core/normal/main.c | 120 ++++++++++++++++++++--------------------- + 3 files changed, 75 insertions(+), 75 deletions(-) + +diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c +index 8191f8cd658..8ca4bf79f09 100644 +--- a/grub-core/kern/ieee1275/init.c ++++ b/grub-core/kern/ieee1275/init.c +@@ -131,23 +131,25 @@ grub_machine_get_bootlocation (char **device, char **path) + grub_free (canon); + } + else +- *device = grub_ieee1275_encode_devname (bootpath); +- grub_free (type); +- +- filename = grub_ieee1275_get_filename (bootpath); +- if (filename) + { +- char *lastslash = grub_strrchr (filename, '\\'); +- +- /* Truncate at last directory. */ +- if (lastslash) ++ filename = grub_ieee1275_get_filename (bootpath); ++ if (filename) + { +- *lastslash = '\0'; +- grub_translate_ieee1275_path (filename); ++ char *lastslash = grub_strrchr (filename, '\\'); + +- *path = filename; +- } ++ /* Truncate at last directory. */ ++ if (lastslash) ++ { ++ *lastslash = '\0'; ++ grub_translate_ieee1275_path (filename); ++ ++ *path = filename; ++ } ++ } ++ *device = grub_ieee1275_encode_devname (bootpath); + } ++ ++ grub_free (type); + grub_free (bootpath); + } + +diff --git a/grub-core/net/net.c b/grub-core/net/net.c +index 578e057e18f..10bfed31b2b 100644 +--- a/grub-core/net/net.c ++++ b/grub-core/net/net.c +@@ -1817,7 +1817,7 @@ grub_net_search_configfile (char *config) + /* Remove the remaining minus sign at the end. */ + config[config_len] = '\0'; + +- return GRUB_ERR_NONE; ++ return GRUB_ERR_FILE_NOT_FOUND; + } + + static struct grub_preboot *fini_hnd; +diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c +index 4190985ad37..aa14499996b 100644 +--- a/grub-core/normal/main.c ++++ b/grub-core/normal/main.c +@@ -331,74 +331,72 @@ grub_enter_normal_mode (const char *config) + grub_boot_time ("Exiting normal mode"); + } + ++static grub_err_t ++grub_try_normal (const char *variable) ++{ ++ char *config; ++ const char *prefix; ++ grub_err_t err = GRUB_ERR_FILE_NOT_FOUND; ++ ++ prefix = grub_env_get (variable); ++ if (!prefix) ++ return GRUB_ERR_FILE_NOT_FOUND; ++ ++ if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0) ++ { ++ grub_size_t config_len; ++ config_len = grub_strlen (prefix) + ++ sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"); ++ config = grub_malloc (config_len); ++ ++ if (! config) ++ return GRUB_ERR_FILE_NOT_FOUND; ++ ++ grub_snprintf (config, config_len, "%s/grub.cfg", prefix); ++ err = grub_net_search_configfile (config); ++ } ++ ++ if (err != GRUB_ERR_NONE) ++ { ++ config = grub_xasprintf ("%s/grub.cfg", prefix); ++ if (config) ++ { ++ grub_file_t file; ++ file = grub_file_open (config); ++ if (file) ++ { ++ grub_file_close (file); ++ err = GRUB_ERR_NONE; ++ } ++ } ++ } ++ ++ if (err == GRUB_ERR_NONE) ++ grub_enter_normal_mode (config); ++ ++ grub_errno = 0; ++ grub_free (config); ++ return err; ++} ++ + /* Enter normal mode from rescue mode. */ + static grub_err_t + grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), + int argc, char *argv[]) + { +- if (argc == 0) +- { +- /* Guess the config filename. It is necessary to make CONFIG static, +- so that it won't get broken by longjmp. */ +- char *config; +- const char *prefix; +- +- prefix = grub_env_get ("fw_path"); +- if (! prefix) +- prefix = grub_env_get ("prefix"); +- +- if (prefix) +- { +- if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0) +- { +- grub_size_t config_len; +- config_len = grub_strlen (prefix) + +- sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"); +- config = grub_malloc (config_len); +- +- if (! config) +- goto quit; +- +- grub_snprintf (config, config_len, "%s/grub.cfg", prefix); +- +- grub_net_search_configfile (config); +- +- grub_enter_normal_mode (config); +- grub_free (config); +- config = NULL; +- } +- +- if (!config) +- { +- config = grub_xasprintf ("%s/grub.cfg", prefix); +- if (config) +- { +- grub_file_t file; +- +- file = grub_file_open (config); +- if (file) +- { +- grub_file_close (file); +- grub_enter_normal_mode (config); +- } +- else +- { +- /* Ignore all errors. */ +- grub_errno = 0; +- } +- grub_free (config); +- } +- } +- } +- else +- { +- grub_enter_normal_mode (0); +- } +- } +- else ++ if (argc) + grub_enter_normal_mode (argv[0]); ++ else ++ { ++ /* Guess the config filename. */ ++ grub_err_t err; ++ err = grub_try_normal ("fw_path"); ++ if (err == GRUB_ERR_FILE_NOT_FOUND) ++ err = grub_try_normal ("prefix"); ++ if (err == GRUB_ERR_FILE_NOT_FOUND) ++ grub_enter_normal_mode (0); ++ } + +-quit: + return 0; + } + diff --git a/SOURCES/0155-Update-info-with-grub.cfg-netboot-selection-order-11.patch b/SOURCES/0155-Update-info-with-grub.cfg-netboot-selection-order-11.patch new file mode 100644 index 0000000..b621d5a --- /dev/null +++ b/SOURCES/0155-Update-info-with-grub.cfg-netboot-selection-order-11.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robert Marshall +Date: Mon, 16 Mar 2015 16:34:51 -0400 +Subject: [PATCH] Update info with grub.cfg netboot selection order (#1148650) + +Added documentation to the grub info page that specifies the order +netboot clients will use to select a grub configuration file. + +Resolves rhbz#1148650 +--- + docs/grub.texi | 42 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 42 insertions(+) + +diff --git a/docs/grub.texi b/docs/grub.texi +index 6b112c18804..ef09c832482 100644 +--- a/docs/grub.texi ++++ b/docs/grub.texi +@@ -2414,6 +2414,48 @@ grub-mknetdir --net-directory=/srv/tftp --subdir=/boot/grub -d /usr/lib/grub/i38 + Then follow instructions printed out by grub-mknetdir on configuring your DHCP + server. + ++The grub.cfg file is placed in the same directory as the path output by ++grub-mknetdir hereafter referred to as FWPATH. GRUB will search for its ++configuration files in order using the following rules where the appended ++value corresponds to a value on the client machine. ++ ++@example ++@group ++@samp{(FWPATH)}/grub.cfg-@samp{(UUID OF NIC)} ++@samp{(FWPATH)}/grub.cfg-@samp{(MAC ADDRESS OF NIC)} ++@samp{(FWPATH)}/grub.cfg-@samp{(IPv4 OR IPv6 ADDRESS)} ++@samp{(FWPATH)}/grub.cfg ++@end group ++@end example ++ ++The client will only attempt to look up an IPv6 address config once, however, ++it will try the IPv4 multiple times. The concrete example below shows what ++would happen under the IPv4 case. ++ ++@example ++@group ++UUID: 7726a678-7fc0-4853-a4f6-c85ac36a120a ++MAC: 52:54:00:ec:33:81 ++IPV4: 10.0.0.130 (0A000082) ++@end group ++@end example ++ ++@example ++@group ++@samp{(FWPATH)}/grub.cfg-7726a678-7fc0-4853-a4f6-c85ac36a120a ++@samp{(FWPATH)}/grub.cfg-52-54-00-ec-33-81 ++@samp{(FWPATH)}/grub.cfg-0A000082 ++@samp{(FWPATH)}/grub.cfg-0A00008 ++@samp{(FWPATH)}/grub.cfg-0A0000 ++@samp{(FWPATH)}/grub.cfg-0A000 ++@samp{(FWPATH)}/grub.cfg-0A00 ++@samp{(FWPATH)}/grub.cfg-0A0 ++@samp{(FWPATH)}/grub.cfg-0A ++@samp{(FWPATH)}/grub.cfg-0 ++@samp{(FWPATH)}/grub.cfg ++@end group ++@end example ++ + After GRUB has started, files on the TFTP server will be accessible via the + @samp{(tftp)} device. + diff --git a/SOURCES/0156-Use-Distribution-Package-Sort-for-grub2-mkconfig-112.patch b/SOURCES/0156-Use-Distribution-Package-Sort-for-grub2-mkconfig-112.patch new file mode 100644 index 0000000..5406f63 --- /dev/null +++ b/SOURCES/0156-Use-Distribution-Package-Sort-for-grub2-mkconfig-112.patch @@ -0,0 +1,446 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robert Marshall +Date: Mon, 16 Mar 2015 14:14:19 -0400 +Subject: [PATCH] Use Distribution Package Sort for grub2-mkconfig (#1124074) + +Users reported that newly installed kernels on their systems installed +with grub-mkconfig would not appear on the grub boot list in order +starting with the most recent. Added an option for rpm-based systems to +use the rpm-sort library to sort kernels instead. + +Resolves rhbz#1124074 +--- + configure.ac | 29 +++++ + Makefile.util.def | 16 +++ + util/grub-rpm-sort.c | 281 ++++++++++++++++++++++++++++++++++++++++++++++ + .gitignore | 1 + + util/grub-mkconfig_lib.in | 8 +- + util/grub-rpm-sort.8 | 12 ++ + 6 files changed, 346 insertions(+), 1 deletion(-) + create mode 100644 util/grub-rpm-sort.c + create mode 100644 util/grub-rpm-sort.8 + +diff --git a/configure.ac b/configure.ac +index 048ce7c89fa..de17e65c4b7 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -65,6 +65,7 @@ grub_TRANSFORM([grub-mkrelpath]) + grub_TRANSFORM([grub-mkrescue]) + grub_TRANSFORM([grub-probe]) + grub_TRANSFORM([grub-reboot]) ++grub_TRANSFORM([grub-rpm-sort]) + grub_TRANSFORM([grub-script-check]) + grub_TRANSFORM([grub-set-default]) + grub_TRANSFORM([grub-sparc64-setup]) +@@ -89,6 +90,7 @@ grub_TRANSFORM([grub-mkrescue.1]) + grub_TRANSFORM([grub-mkstandalone.3]) + grub_TRANSFORM([grub-ofpathname.3]) + grub_TRANSFORM([grub-probe.3]) ++grub_TRANSFORM([grub-rpm-sort.8]) + grub_TRANSFORM([grub-reboot.3]) + grub_TRANSFORM([grub-render-label.3]) + grub_TRANSFORM([grub-script-check.3]) +@@ -1543,6 +1545,33 @@ fi + + AC_SUBST([LIBDEVMAPPER]) + ++AC_ARG_ENABLE([rpm-sort], ++ [AS_HELP_STRING([--enable-rpm-sort], ++ [enable native rpm sorting of kernels in grub (default=guessed)])]) ++if test x"$enable_rpm-sort" = xno ; then ++ rpm_sort_excuse="explicitly disabled" ++fi ++ ++if test x"$rpm_sort_excuse" = x ; then ++ # Check for rpmlib header. ++ AC_CHECK_HEADER([rpm/rpmlib.h], [], ++ [rpm_sort_excuse="need rpm/rpmlib header"]) ++fi ++ ++if test x"$rpm_sort_excuse" = x ; then ++ # Check for rpm library. ++ AC_CHECK_LIB([rpm], [rpmvercmp], [], ++ [rpm_sort_excuse="rpmlib missing rpmvercmp"]) ++fi ++ ++if test x"$rpm_sort_excuse" = x ; then ++ LIBRPM="-lrpm"; ++ AC_DEFINE([HAVE_RPM], [1], ++ [Define to 1 if you have the rpm library.]) ++fi ++ ++AC_SUBST([LIBRPM]) ++ + LIBGEOM= + if test x$host_kernel = xkfreebsd; then + AC_CHECK_LIB([geom], [geom_gettree], [], +diff --git a/Makefile.util.def b/Makefile.util.def +index 87029a10dfb..3ac75720466 100644 +--- a/Makefile.util.def ++++ b/Makefile.util.def +@@ -675,6 +675,22 @@ program = { + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; + }; + ++program = { ++ name = grub-rpm-sort; ++ mansection = 8; ++ installdir = sbin; ++ ++ common = grub-core/kern/emu/misc.c; ++ common = grub-core/kern/emu/argp_common.c; ++ common = grub-core/osdep/init.c; ++ common = util/misc.c; ++ common = util/grub-rpm-sort.c; ++ ++ ldadd = grub-core/gnulib/libgnu.a; ++ ldadd = libgrubkern.a; ++ ldadd = '$(LIBDEVMAPPER) $(LIBRPM)'; ++}; ++ + script = { + name = grub-mkconfig; + common = util/grub-mkconfig.in; +diff --git a/util/grub-rpm-sort.c b/util/grub-rpm-sort.c +new file mode 100644 +index 00000000000..f33bd1ed568 +--- /dev/null ++++ b/util/grub-rpm-sort.c +@@ -0,0 +1,281 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static size_t ++read_file (const char *input, char **ret) ++{ ++ FILE *in; ++ size_t s; ++ size_t sz = 2048; ++ size_t offset = 0; ++ char *text; ++ ++ if (!strcmp(input, "-")) ++ in = stdin; ++ else ++ in = grub_util_fopen(input, "r"); ++ ++ text = xmalloc (sz); ++ ++ if (!in) ++ grub_util_error (_("cannot open `%s': %s"), input, strerror (errno)); ++ ++ while ((s = fread (text + offset, 1, sz - offset, in)) != 0) ++ { ++ offset += s; ++ if (sz - offset == 0) ++ { ++ sz += 2048; ++ text = xrealloc (text, sz); ++ } ++ } ++ ++ text[offset] = '\0'; ++ *ret = text; ++ ++ if (in != stdin) ++ fclose(in); ++ ++ return offset + 1; ++} ++ ++/* returns name/version/release */ ++/* NULL string pointer returned if nothing found */ ++static void ++split_package_string (char *package_string, char **name, ++ char **version, char **release) ++{ ++ char *package_version, *package_release; ++ ++ /* Release */ ++ package_release = strrchr (package_string, '-'); ++ ++ if (package_release != NULL) ++ *package_release++ = '\0'; ++ ++ *release = package_release; ++ ++ /* Version */ ++ package_version = strrchr(package_string, '-'); ++ ++ if (package_version != NULL) ++ *package_version++ = '\0'; ++ ++ *version = package_version; ++ /* Name */ ++ *name = package_string; ++ ++ /* Bubble up non-null values from release to name */ ++ if (*name == NULL) ++ { ++ *name = (*version == NULL ? *release : *version); ++ *version = *release; ++ *release = NULL; ++ } ++ if (*version == NULL) ++ { ++ *version = *release; ++ *release = NULL; ++ } ++} ++ ++/* ++ * package name-version-release comparator for qsort ++ * expects p, q which are pointers to character strings (char *) ++ * which will not be altered in this function ++ */ ++static int ++package_version_compare (const void *p, const void *q) ++{ ++ char *local_p, *local_q; ++ char *lhs_name, *lhs_version, *lhs_release; ++ char *rhs_name, *rhs_version, *rhs_release; ++ int vercmpflag = 0; ++ ++ local_p = alloca (strlen (*(char * const *)p) + 1); ++ local_q = alloca (strlen (*(char * const *)q) + 1); ++ ++ /* make sure these allocated */ ++ assert (local_p); ++ assert (local_q); ++ ++ strcpy (local_p, *(char * const *)p); ++ strcpy (local_q, *(char * const *)q); ++ ++ split_package_string (local_p, &lhs_name, &lhs_version, &lhs_release); ++ split_package_string (local_q, &rhs_name, &rhs_version, &rhs_release); ++ ++ /* Check Name and return if unequal */ ++ vercmpflag = rpmvercmp ((lhs_name == NULL ? "" : lhs_name), ++ (rhs_name == NULL ? "" : rhs_name)); ++ if (vercmpflag != 0) ++ return vercmpflag; ++ ++ /* Check version and return if unequal */ ++ vercmpflag = rpmvercmp ((lhs_version == NULL ? "" : lhs_version), ++ (rhs_version == NULL ? "" : rhs_version)); ++ if (vercmpflag != 0) ++ return vercmpflag; ++ ++ /* Check release and return the version compare value */ ++ vercmpflag = rpmvercmp ((lhs_release == NULL ? "" : lhs_release), ++ (rhs_release == NULL ? "" : rhs_release)); ++ ++ return vercmpflag; ++} ++ ++static void ++add_input (const char *filename, char ***package_names, size_t *n_package_names) ++{ ++ char *orig_input_buffer = NULL; ++ char *input_buffer; ++ char *position_of_newline; ++ char **names = *package_names; ++ char **new_names = NULL; ++ size_t n_names = *n_package_names; ++ ++ if (!*package_names) ++ new_names = names = xmalloc (sizeof (char *) * 2); ++ ++ if (read_file (filename, &orig_input_buffer) < 2) ++ { ++ if (new_names) ++ free (new_names); ++ if (orig_input_buffer) ++ free (orig_input_buffer); ++ return; ++ } ++ ++ input_buffer = orig_input_buffer; ++ while (input_buffer && *input_buffer && ++ (position_of_newline = strchrnul (input_buffer, '\n'))) ++ { ++ size_t sz = position_of_newline - input_buffer; ++ char *new; ++ ++ if (sz == 0) ++ { ++ input_buffer = position_of_newline + 1; ++ continue; ++ } ++ ++ new = xmalloc (sz+1); ++ strncpy (new, input_buffer, sz); ++ new[sz] = '\0'; ++ ++ names = xrealloc (names, sizeof (char *) * (n_names + 1)); ++ names[n_names] = new; ++ n_names++; ++ ++ /* move buffer ahead to next line */ ++ input_buffer = position_of_newline + 1; ++ if (*position_of_newline == '\0') ++ input_buffer = NULL; ++ } ++ ++ free (orig_input_buffer); ++ ++ *package_names = names; ++ *n_package_names = n_names; ++} ++ ++static char * ++help_filter (int key, const char *text, void *input __attribute__ ((unused))) ++{ ++ return (char *)text; ++} ++ ++static struct argp_option options[] = { ++ { 0, } ++}; ++ ++struct arguments ++{ ++ size_t ninputs; ++ size_t input_max; ++ char **inputs; ++}; ++ ++static error_t ++argp_parser (int key, char *arg, struct argp_state *state) ++{ ++ struct arguments *arguments = state->input; ++ switch (key) ++ { ++ case ARGP_KEY_ARG: ++ assert (arguments->ninputs < arguments->input_max); ++ arguments->inputs[arguments->ninputs++] = xstrdup (arg); ++ break; ++ default: ++ return ARGP_ERR_UNKNOWN; ++ } ++ return 0; ++} ++ ++static struct argp argp = { ++ options, argp_parser, N_("[INPUT_FILES]"), ++ N_("Sort a list of strings in RPM version sort order."), ++ NULL, help_filter, NULL ++}; ++ ++int ++main (int argc, char *argv[]) ++{ ++ struct arguments arguments; ++ char **package_names = NULL; ++ size_t n_package_names = 0; ++ int i; ++ ++ grub_util_host_init (&argc, &argv); ++ ++ memset (&arguments, 0, sizeof (struct arguments)); ++ arguments.input_max = argc+1; ++ arguments.inputs = xmalloc ((arguments.input_max + 1) ++ * sizeof (arguments.inputs[0])); ++ memset (arguments.inputs, 0, (arguments.input_max + 1) ++ * sizeof (arguments.inputs[0])); ++ ++ /* Parse our arguments */ ++ if (argp_parse (&argp, argc, argv, 0, 0, &arguments) != 0) ++ grub_util_error ("%s", _("Error in parsing command line arguments\n")); ++ ++ /* If there's no inputs in argv, add one for stdin */ ++ if (!arguments.ninputs) ++ { ++ arguments.ninputs = 1; ++ arguments.inputs[0] = xmalloc (2); ++ strcpy(arguments.inputs[0], "-"); ++ } ++ ++ for (i = 0; i < arguments.ninputs; i++) ++ add_input(arguments.inputs[i], &package_names, &n_package_names); ++ ++ if (package_names == NULL || n_package_names < 1) ++ grub_util_error ("%s", _("Invalid input\n")); ++ ++ qsort (package_names, n_package_names, sizeof (char *), ++ package_version_compare); ++ ++ /* send sorted list to stdout */ ++ for (i = 0; i < n_package_names; i++) ++ { ++ fprintf (stdout, "%s\n", package_names[i]); ++ free (package_names[i]); ++ } ++ ++ free (package_names); ++ for (i = 0; i < arguments.ninputs; i++) ++ free (arguments.inputs[i]); ++ ++ free (arguments.inputs); ++ ++ return 0; ++} +diff --git a/.gitignore b/.gitignore +index 18ab8e81278..b6c45776a4d 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -237,6 +237,7 @@ po/POTFILES.in + po/POTFILES-shell.in + /grub-glue-efi + /grub-render-label ++grub-rpm-sort + /grub-glue-efi.exe + /grub-render-label.exe + grub-core/gnulib/locale.h +diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in +index 5c9ed84a5e7..e85b60c322a 100644 +--- a/util/grub-mkconfig_lib.in ++++ b/util/grub-mkconfig_lib.in +@@ -213,6 +213,12 @@ version_sort () + esac + } + ++if [ "x$RPMLIB" = x ]; then ++ kernel_sort=version_sort ++else ++ kernel_sort="${sbindir}/grub-rpm-sort" ++fi ++ + version_test_numeric () + { + version_test_numeric_a="$1" +@@ -229,7 +235,7 @@ version_test_numeric () + version_test_numeric_a="$version_test_numeric_b" + version_test_numeric_b="$version_test_numeric_c" + fi +- if (echo "$version_test_numeric_a" ; echo "$version_test_numeric_b") | version_sort | head -n 1 | grep -qx "$version_test_numeric_b" ; then ++ if (echo "$version_test_numeric_a" ; echo "$version_test_numeric_b") | "$kernel_sort" | head -n 1 | grep -qx "$version_test_numeric_b" ; then + return 0 + else + return 1 +diff --git a/util/grub-rpm-sort.8 b/util/grub-rpm-sort.8 +new file mode 100644 +index 00000000000..8ce21488448 +--- /dev/null ++++ b/util/grub-rpm-sort.8 +@@ -0,0 +1,12 @@ ++.TH GRUB-RPM-SORT 8 "Wed Feb 26 2014" ++.SH NAME ++\fBgrub-rpm-sort\fR \(em Sort input according to RPM version compare. ++ ++.SH SYNOPSIS ++\fBgrub-rpm-sort\fR [OPTIONS]. ++ ++.SH DESCRIPTION ++You should not normally run this program directly. Use grub-mkconfig instead. ++ ++.SH SEE ALSO ++.BR "info grub" diff --git a/SOURCES/0157-efidisk-move-device-path-helpers-in-core-for-efinet.patch b/SOURCES/0157-efidisk-move-device-path-helpers-in-core-for-efinet.patch new file mode 100644 index 0000000..e57c685 --- /dev/null +++ b/SOURCES/0157-efidisk-move-device-path-helpers-in-core-for-efinet.patch @@ -0,0 +1,204 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Thu, 7 May 2015 20:37:16 +0300 +Subject: [PATCH] efidisk: move device path helpers in core for efinet + +--- + grub-core/disk/efi/efidisk.c | 61 ++++++++------------------------------------ + grub-core/kern/efi/efi.c | 41 +++++++++++++++++++++++++++++ + include/grub/efi/efi.h | 4 +++ + 3 files changed, 55 insertions(+), 51 deletions(-) + +diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c +index 3b12c349923..845c66fa9ab 100644 +--- a/grub-core/disk/efi/efidisk.c ++++ b/grub-core/disk/efi/efidisk.c +@@ -43,47 +43,6 @@ static struct grub_efidisk_data *fd_devices; + static struct grub_efidisk_data *hd_devices; + static struct grub_efidisk_data *cd_devices; + +-/* Duplicate a device path. */ +-static grub_efi_device_path_t * +-duplicate_device_path (const grub_efi_device_path_t *dp) +-{ +- grub_efi_device_path_t *p; +- grub_size_t total_size = 0; +- +- for (p = (grub_efi_device_path_t *) dp; +- ; +- p = GRUB_EFI_NEXT_DEVICE_PATH (p)) +- { +- total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p); +- if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p)) +- break; +- } +- +- p = grub_malloc (total_size); +- if (! p) +- return 0; +- +- grub_memcpy (p, dp, total_size); +- return p; +-} +- +-/* Return the device path node right before the end node. */ +-static grub_efi_device_path_t * +-find_last_device_path (const grub_efi_device_path_t *dp) +-{ +- grub_efi_device_path_t *next, *p; +- +- if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp)) +- return 0; +- +- for (p = (grub_efi_device_path_t *) dp, next = GRUB_EFI_NEXT_DEVICE_PATH (p); +- ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (next); +- p = next, next = GRUB_EFI_NEXT_DEVICE_PATH (next)) +- ; +- +- return p; +-} +- + static struct grub_efidisk_data * + make_devices (void) + { +@@ -110,7 +69,7 @@ make_devices (void) + if (! dp) + continue; + +- ldp = find_last_device_path (dp); ++ ldp = grub_efi_find_last_device_path (dp); + if (! ldp) + /* This is empty. Why? */ + continue; +@@ -150,11 +109,11 @@ find_parent_device (struct grub_efidisk_data *devices, + grub_efi_device_path_t *dp, *ldp; + struct grub_efidisk_data *parent; + +- dp = duplicate_device_path (d->device_path); ++ dp = grub_efi_duplicate_device_path (d->device_path); + if (! dp) + return 0; + +- ldp = find_last_device_path (dp); ++ ldp = grub_efi_find_last_device_path (dp); + ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; + ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; + ldp->length = sizeof (*ldp); +@@ -180,11 +139,11 @@ is_child (struct grub_efidisk_data *child, + grub_efi_device_path_t *dp, *ldp; + int ret; + +- dp = duplicate_device_path (child->device_path); ++ dp = grub_efi_duplicate_device_path (child->device_path); + if (! dp) + return 0; + +- ldp = find_last_device_path (dp); ++ ldp = grub_efi_find_last_device_path (dp); + ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; + ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; + ldp->length = sizeof (*ldp); +@@ -207,8 +166,8 @@ add_device (struct grub_efidisk_data **devices, struct grub_efidisk_data *d) + { + int ret; + +- ret = grub_efi_compare_device_paths (find_last_device_path ((*p)->device_path), +- find_last_device_path (d->device_path)); ++ ret = grub_efi_compare_device_paths (grub_efi_find_last_device_path ((*p)->device_path), ++ grub_efi_find_last_device_path (d->device_path)); + if (ret == 0) + ret = grub_efi_compare_device_paths ((*p)->device_path, + d->device_path); +@@ -795,7 +754,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) + if (! dp) + return 0; + +- ldp = find_last_device_path (dp); ++ ldp = grub_efi_find_last_device_path (dp); + if (! ldp) + return 0; + +@@ -811,14 +770,14 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) + + /* It is necessary to duplicate the device path so that GRUB + can overwrite it. */ +- dup_dp = duplicate_device_path (dp); ++ dup_dp = grub_efi_duplicate_device_path (dp); + if (! dup_dp) + return 0; + + while (1) + { + grub_efi_device_path_t *dup_ldp; +- dup_ldp = find_last_device_path (dup_dp); ++ dup_ldp = grub_efi_find_last_device_path (dup_dp); + if (!(GRUB_EFI_DEVICE_PATH_TYPE (dup_ldp) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE + && (GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE + || GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE))) +diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c +index d99a6fbdf0d..c80d85b677e 100644 +--- a/grub-core/kern/efi/efi.c ++++ b/grub-core/kern/efi/efi.c +@@ -423,6 +423,47 @@ grub_efi_get_device_path (grub_efi_handle_t handle) + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); + } + ++/* Return the device path node right before the end node. */ ++grub_efi_device_path_t * ++grub_efi_find_last_device_path (const grub_efi_device_path_t *dp) ++{ ++ grub_efi_device_path_t *next, *p; ++ ++ if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp)) ++ return 0; ++ ++ for (p = (grub_efi_device_path_t *) dp, next = GRUB_EFI_NEXT_DEVICE_PATH (p); ++ ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (next); ++ p = next, next = GRUB_EFI_NEXT_DEVICE_PATH (next)) ++ ; ++ ++ return p; ++} ++ ++/* Duplicate a device path. */ ++grub_efi_device_path_t * ++grub_efi_duplicate_device_path (const grub_efi_device_path_t *dp) ++{ ++ grub_efi_device_path_t *p; ++ grub_size_t total_size = 0; ++ ++ for (p = (grub_efi_device_path_t *) dp; ++ ; ++ p = GRUB_EFI_NEXT_DEVICE_PATH (p)) ++ { ++ total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p); ++ if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p)) ++ break; ++ } ++ ++ p = grub_malloc (total_size); ++ if (! p) ++ return 0; ++ ++ grub_memcpy (p, dp, total_size); ++ return p; ++} ++ + static void + dump_vendor_path (const char *type, grub_efi_vendor_device_path_t *vendor) + { +diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h +index a000c383e81..22456327e13 100644 +--- a/include/grub/efi/efi.h ++++ b/include/grub/efi/efi.h +@@ -56,6 +56,10 @@ void EXPORT_FUNC(grub_efi_print_device_path) (grub_efi_device_path_t *dp); + char *EXPORT_FUNC(grub_efi_get_filename) (grub_efi_device_path_t *dp); + grub_efi_device_path_t * + EXPORT_FUNC(grub_efi_get_device_path) (grub_efi_handle_t handle); ++grub_efi_device_path_t * ++EXPORT_FUNC(grub_efi_find_last_device_path) (const grub_efi_device_path_t *dp); ++grub_efi_device_path_t * ++EXPORT_FUNC(grub_efi_duplicate_device_path) (const grub_efi_device_path_t *dp); + grub_err_t EXPORT_FUNC (grub_efi_finish_boot_services) (grub_efi_uintn_t *outbuf_size, void *outbuf, + grub_efi_uintn_t *map_key, + grub_efi_uintn_t *efi_desc_size, diff --git a/SOURCES/0158-efinet-Check-for-immediate-completition.patch b/SOURCES/0158-efinet-Check-for-immediate-completition.patch new file mode 100644 index 0000000..b337ffc --- /dev/null +++ b/SOURCES/0158-efinet-Check-for-immediate-completition.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 27 Mar 2015 14:27:56 +0100 +Subject: [PATCH] efinet: Check for immediate completition. + +This both speeds GRUB up and workarounds unexpected EFI behaviour. +--- + grub-core/net/drivers/efi/efinet.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index a6e4c7992f7..78df215be12 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -37,11 +37,12 @@ send_card_buffer (struct grub_net_card *dev, + grub_efi_status_t st; + grub_efi_simple_network_t *net = dev->efi_net; + grub_uint64_t limit_time = grub_get_time_ms () + 4000; ++ void *txbuf; + + if (dev->txbusy) + while (1) + { +- void *txbuf = NULL; ++ txbuf = NULL; + st = efi_call_3 (net->get_status, net, 0, &txbuf); + if (st != GRUB_EFI_SUCCESS) + return grub_error (GRUB_ERR_IO, +@@ -74,7 +75,18 @@ send_card_buffer (struct grub_net_card *dev, + dev->txbuf, NULL, NULL, NULL); + if (st != GRUB_EFI_SUCCESS) + return grub_error (GRUB_ERR_IO, N_("couldn't send network packet")); +- dev->txbusy = 1; ++ ++ /* ++ The card may have sent out the packet immediately - set txbusy ++ to 0 in this case. ++ Cases were observed where checking txbuf at the next call ++ of send_card_buffer() is too late: 0 is returned in txbuf and ++ we run in the GRUB_ERR_TIMEOUT case above. ++ Perhaps a timeout in the FW has discarded the recycle buffer. ++ */ ++ st = efi_call_3 (net->get_status, net, 0, &txbuf); ++ dev->txbusy = !(st == GRUB_EFI_SUCCESS && txbuf == dev->txbuf); ++ + return GRUB_ERR_NONE; + } + diff --git a/SOURCES/0159-efinet-memory-leak-on-module-removal.patch b/SOURCES/0159-efinet-memory-leak-on-module-removal.patch new file mode 100644 index 0000000..022222a --- /dev/null +++ b/SOURCES/0159-efinet-memory-leak-on-module-removal.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Mon, 4 May 2015 08:08:57 +0300 +Subject: [PATCH] efinet: memory leak on module removal + +--- + grub-core/net/drivers/efi/efinet.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index 78df215be12..810adf38fe6 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -294,6 +294,12 @@ GRUB_MOD_FINI(efinet) + + FOR_NET_CARDS_SAFE (card, next) + if (card->driver == &efidriver) +- grub_net_card_unregister (card); ++ { ++ grub_net_card_unregister (card); ++ grub_free (card->txbuf); ++ grub_free (card->rcvbuf); ++ grub_free (card->name); ++ grub_free (card); ++ } + } + diff --git a/SOURCES/0160-efinet-cannot-free-const-char-pointer.patch b/SOURCES/0160-efinet-cannot-free-const-char-pointer.patch new file mode 100644 index 0000000..865ccd9 --- /dev/null +++ b/SOURCES/0160-efinet-cannot-free-const-char-pointer.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Mon, 4 May 2015 08:39:29 +0300 +Subject: [PATCH] efinet: cannot free const char * pointer + +--- + grub-core/net/drivers/efi/efinet.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index 810adf38fe6..bb863e65a38 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -298,7 +298,7 @@ GRUB_MOD_FINI(efinet) + grub_net_card_unregister (card); + grub_free (card->txbuf); + grub_free (card->rcvbuf); +- grub_free (card->name); ++ grub_free ((char *)card->name); + grub_free (card); + } + } diff --git a/SOURCES/0161-Revert-efinet-memory-leak-on-module-removal.patch b/SOURCES/0161-Revert-efinet-memory-leak-on-module-removal.patch new file mode 100644 index 0000000..f1cf7e0 --- /dev/null +++ b/SOURCES/0161-Revert-efinet-memory-leak-on-module-removal.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Mon, 4 May 2015 09:13:53 +0300 +Subject: [PATCH] Revert "efinet: memory leak on module removal" + +This reverts commits 47b2bee3ef0ea60fc3f5bfc37f3784e559385297 +and 8d3c4544ffdd0289a4b0bdeb0cdc6355f801a4b3. It is not safe +to free allocated cards, dangling pointers main remain. Such +cleanup requires more changes in net core. +--- + grub-core/net/drivers/efi/efinet.c | 8 +------- + 1 file changed, 1 insertion(+), 7 deletions(-) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index bb863e65a38..78df215be12 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -294,12 +294,6 @@ GRUB_MOD_FINI(efinet) + + FOR_NET_CARDS_SAFE (card, next) + if (card->driver == &efidriver) +- { +- grub_net_card_unregister (card); +- grub_free (card->txbuf); +- grub_free (card->rcvbuf); +- grub_free ((char *)card->name); +- grub_free (card); +- } ++ grub_net_card_unregister (card); + } + diff --git a/SOURCES/0162-efinet-skip-virtual-IPv4-and-IPv6-devices-when-enume.patch b/SOURCES/0162-efinet-skip-virtual-IPv4-and-IPv6-devices-when-enume.patch new file mode 100644 index 0000000..f21a921 --- /dev/null +++ b/SOURCES/0162-efinet-skip-virtual-IPv4-and-IPv6-devices-when-enume.patch @@ -0,0 +1,94 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Thu, 7 May 2015 20:37:17 +0300 +Subject: [PATCH] efinet: skip virtual IPv4 and IPv6 devices when enumerating + cards + +EDK2 PXE driver creates two child devices - IPv4 and IPv6 - with +bound SNP instance. This means we get three cards for every physical +adapter when enumerating. Not only is this confusing, this may result +in grub ignoring packets that come in via the "wrong" card. + +Example of device hierarchy is + + Ctrl[91] PciRoot(0x0)/Pci(0x3,0x0) + Ctrl[95] PciRoot(0x0)/Pci(0x3,0x0)/MAC(525400123456,0x1) + Ctrl[B4] PciRoot(0x0)/Pci(0x3,0x0)/MAC(525400123456,0x1)/IPv4(0.0.0.0) + Ctrl[BC] PciRoot(0x0)/Pci(0x3,0x0)/MAC(525400123456,0x1)/IPv6(0000:0000:0000:0000:0000:0000:0000:0000) + +Skip PXE created virtual devices when enumerating cards. Make sure to +find real card when applying initial autoconfiguration during PXE boot, +this information is associated with one of child devices. +--- + grub-core/net/drivers/efi/efinet.c | 51 +++++++++++++++++++++++++++++++++++++- + 1 file changed, 50 insertions(+), 1 deletion(-) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index 78df215be12..caa7b50228b 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -174,6 +174,29 @@ grub_efinet_findcards (void) + { + grub_efi_simple_network_t *net; + struct grub_net_card *card; ++ grub_efi_device_path_t *dp, *parent = NULL, *child = NULL; ++ ++ /* EDK2 UEFI PXE driver creates IPv4 and IPv6 messaging devices as ++ children of main MAC messaging device. We only need one device with ++ bound SNP per physical card, otherwise they compete with each other ++ when polling for incoming packets. ++ */ ++ dp = grub_efi_get_device_path (*handle); ++ if (!dp) ++ continue; ++ for (; ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp); dp = GRUB_EFI_NEXT_DEVICE_PATH (dp)) ++ { ++ parent = child; ++ child = dp; ++ } ++ if (child ++ && GRUB_EFI_DEVICE_PATH_TYPE (child) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE ++ && (GRUB_EFI_DEVICE_PATH_SUBTYPE (child) == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE ++ || GRUB_EFI_DEVICE_PATH_SUBTYPE (child) == GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE) ++ && parent ++ && GRUB_EFI_DEVICE_PATH_TYPE (parent) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE ++ && GRUB_EFI_DEVICE_PATH_SUBTYPE (parent) == GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE) ++ continue; + + net = grub_efi_open_protocol (*handle, &net_io_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); +@@ -252,7 +275,33 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + if (! cdp) + continue; + if (grub_efi_compare_device_paths (dp, cdp) != 0) +- continue; ++ { ++ grub_efi_device_path_t *ldp, *dup_dp, *dup_ldp; ++ int match; ++ ++ /* EDK2 UEFI PXE driver creates pseudo devices with type IPv4/IPv6 ++ as children of Ethernet card and binds PXE and Load File protocols ++ to it. Loaded Image Device Path protocol will point to these pseudo ++ devices. We skip them when enumerating cards, so here we need to ++ find matching MAC 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)) ++ continue; ++ dup_dp = grub_efi_duplicate_device_path (dp); ++ if (!dup_dp) ++ continue; ++ 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); ++ match = grub_efi_compare_device_paths (dup_dp, cdp) == 0; ++ grub_free (dup_dp); ++ if (!match) ++ continue; ++ } + pxe = grub_efi_open_protocol (hnd, &pxe_io_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (! pxe) diff --git a/SOURCES/0163-efinet-open-Simple-Network-Protocol-exclusively.patch b/SOURCES/0163-efinet-open-Simple-Network-Protocol-exclusively.patch new file mode 100644 index 0000000..c26954d --- /dev/null +++ b/SOURCES/0163-efinet-open-Simple-Network-Protocol-exclusively.patch @@ -0,0 +1,86 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Thu, 7 May 2015 20:37:17 +0300 +Subject: [PATCH] efinet: open Simple Network Protocol exclusively + +EDK2 network stack is based on Managed Network Protocol which is layered +on top of Simple Management Protocol and does background polling. This +polling races with grub for received (and probably trasmitted) packets +which causes either serious slowdown or complete failure to load files. + +Open SNP device exclusively. This destroys all child MNP instances and +stops background polling. + +Exclusive open cannot be done when enumerating cards, as it would destroy +PXE information we need to autoconfigure interface; and it cannot be done +during autoconfiguration as we need to do it for non-PXE boot as well. So +move SNP open to card ->open method and add matching ->close to clean up. + +Based on patch from Mark Salter + +Also-By: Mark Salter +Closes: 41731 +--- + grub-core/net/drivers/efi/efinet.c | 46 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 46 insertions(+) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index caa7b50228b..6a1dd1f9dff 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -142,9 +142,55 @@ get_card_packet (struct grub_net_card *dev) + return nb; + } + ++static grub_err_t ++open_card (struct grub_net_card *dev) ++{ ++ grub_efi_simple_network_t *net; ++ ++ /* Try to reopen SNP exlusively to close any active MNP protocol instance ++ that may compete for packet polling ++ */ ++ net = grub_efi_open_protocol (dev->efi_handle, &net_io_guid, ++ GRUB_EFI_OPEN_PROTOCOL_BY_EXCLUSIVE); ++ if (net) ++ { ++ if (net->mode->state == GRUB_EFI_NETWORK_STOPPED ++ && efi_call_1 (net->start, net) != GRUB_EFI_SUCCESS) ++ return grub_error (GRUB_ERR_NET_NO_CARD, "%s: net start failed", ++ dev->name); ++ ++ if (net->mode->state == GRUB_EFI_NETWORK_STOPPED) ++ return grub_error (GRUB_ERR_NET_NO_CARD, "%s: card stopped", ++ dev->name); ++ ++ if (net->mode->state == GRUB_EFI_NETWORK_STARTED ++ && efi_call_3 (net->initialize, net, 0, 0) != GRUB_EFI_SUCCESS) ++ return grub_error (GRUB_ERR_NET_NO_CARD, "%s: net initialize failed", ++ dev->name); ++ ++ efi_call_4 (grub_efi_system_table->boot_services->close_protocol, ++ dev->efi_net, &net_io_guid, ++ grub_efi_image_handle, dev->efi_handle); ++ dev->efi_net = net; ++ } ++ ++ /* If it failed we just try to run as best as we can */ ++ return GRUB_ERR_NONE; ++} ++ ++static void ++close_card (struct grub_net_card *dev) ++{ ++ efi_call_4 (grub_efi_system_table->boot_services->close_protocol, ++ dev->efi_net, &net_io_guid, ++ grub_efi_image_handle, dev->efi_handle); ++} ++ + static struct grub_net_card_driver efidriver = + { + .name = "efinet", ++ .open = open_card, ++ .close = close_card, + .send = send_card_buffer, + .recv = get_card_packet + }; diff --git a/SOURCES/0164-efinet-enable-hardware-filters-when-opening-interfac.patch b/SOURCES/0164-efinet-enable-hardware-filters-when-opening-interfac.patch new file mode 100644 index 0000000..e914ac4 --- /dev/null +++ b/SOURCES/0164-efinet-enable-hardware-filters-when-opening-interfac.patch @@ -0,0 +1,104 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Tue, 16 Jun 2015 19:52:45 +0300 +Subject: [PATCH] efinet: enable hardware filters when opening interface + +Exclusive open on SNP will close all existing protocol instances which +may disable all receive filters on interface. Reinstall them after we +opened protocol exclusively. + +Also follow UEFI specification recommendation and stop interfaces when +closing them: + +Unexpected system errors, reboots and hangs can occur if an OS is loaded +and the network devices are not Shutdown() and Stopped(). + +Also by: Mark Salter +Closes: 45204 +--- + grub-core/net/drivers/efi/efinet.c | 25 +++++++++++++++++++++++++ + include/grub/efi/api.h | 20 +++++++++++++++++--- + 2 files changed, 42 insertions(+), 3 deletions(-) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index 6a1dd1f9dff..7b8c4a59d10 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -168,6 +168,29 @@ open_card (struct grub_net_card *dev) + return grub_error (GRUB_ERR_NET_NO_CARD, "%s: net initialize failed", + dev->name); + ++ /* Enable hardware receive filters if driver declares support for it. ++ We need unicast and broadcast and additionaly all nodes and ++ solicited multicast for IPv6. Solicited multicast is per-IPv6 ++ address and we currently do not have API to do it so simply ++ try to enable receive of all multicast packets or evertyhing in ++ the worst case (i386 PXE driver always enables promiscuous too). ++ ++ This does trust firmware to do what it claims to do. ++ */ ++ if (net->mode->receive_filter_mask) ++ { ++ grub_uint32_t filters = GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | ++ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST | ++ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; ++ ++ filters &= net->mode->receive_filter_mask; ++ if (!(filters & GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST)) ++ filters |= (net->mode->receive_filter_mask & ++ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS); ++ ++ efi_call_6 (net->receive_filters, net, filters, 0, 0, 0, NULL); ++ } ++ + efi_call_4 (grub_efi_system_table->boot_services->close_protocol, + dev->efi_net, &net_io_guid, + grub_efi_image_handle, dev->efi_handle); +@@ -181,6 +204,8 @@ open_card (struct grub_net_card *dev) + static void + close_card (struct grub_net_card *dev) + { ++ efi_call_1 (dev->efi_net->shutdown, dev->efi_net); ++ efi_call_1 (dev->efi_net->stop, dev->efi_net); + efi_call_4 (grub_efi_system_table->boot_services->close_protocol, + dev->efi_net, &net_io_guid, + grub_efi_image_handle, dev->efi_handle); +diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h +index 142340372e1..029ee92f5d0 100644 +--- a/include/grub/efi/api.h ++++ b/include/grub/efi/api.h +@@ -1564,17 +1564,31 @@ enum + GRUB_EFI_NETWORK_INITIALIZED, + }; + ++enum ++ { ++ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST = 0x01, ++ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST = 0x02, ++ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST = 0x04, ++ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS = 0x08, ++ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST = 0x10, ++ }; ++ + struct grub_efi_simple_network + { + grub_uint64_t revision; + grub_efi_status_t (*start) (struct grub_efi_simple_network *this); +- void (*stop) (void); ++ grub_efi_status_t (*stop) (struct grub_efi_simple_network *this); + grub_efi_status_t (*initialize) (struct grub_efi_simple_network *this, + grub_efi_uintn_t extra_rx, + grub_efi_uintn_t extra_tx); + void (*reset) (void); +- void (*shutdown) (void); +- void (*receive_filters) (void); ++ grub_efi_status_t (*shutdown) (struct grub_efi_simple_network *this); ++ grub_efi_status_t (*receive_filters) (struct grub_efi_simple_network *this, ++ grub_uint32_t enable, ++ grub_uint32_t disable, ++ grub_efi_boolean_t reset_mcast_filter, ++ grub_efi_uintn_t mcast_filter_count, ++ grub_efi_mac_address_t *mcast_filter); + void (*station_address) (void); + void (*statistics) (void); + void (*mcastiptomac) (void); diff --git a/SOURCES/0165-efinet-handle-get_status-on-buggy-firmware-properly.patch b/SOURCES/0165-efinet-handle-get_status-on-buggy-firmware-properly.patch new file mode 100644 index 0000000..22e2bcc --- /dev/null +++ b/SOURCES/0165-efinet-handle-get_status-on-buggy-firmware-properly.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Thu, 6 Aug 2015 10:49:46 -0700 +Subject: [PATCH] efinet: handle get_status() on buggy firmware properly + +The EFI spec indicates that get_status() should return the address of the buffer +we passed into transmit to indicate the the buffer was transmitted. However we +have boxes where the firmware returns some arbitrary address instead, which +makes grub think that we've not sent anything. So since we have the SNP stuff +opened in exclusive mode just assume any non-NULL txbuf means that our transmit +occurred properly. This makes grub able to do its networking stuff properly on +our broken firmware. Thanks, + +cc: Peter Jones +Signed-off-by: Josef Bacik +--- + grub-core/net/drivers/efi/efinet.c | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index 7b8c4a59d10..ea0e0ca360e 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -47,19 +47,19 @@ send_card_buffer (struct grub_net_card *dev, + if (st != GRUB_EFI_SUCCESS) + return grub_error (GRUB_ERR_IO, + N_("couldn't send network packet")); +- if (txbuf == dev->txbuf) ++ /* ++ Some buggy firmware could return an arbitrary address instead of the ++ txbuf address we trasmitted, so just check that txbuf is non NULL ++ for success. This is ok because we open the SNP protocol in ++ exclusive mode so we know we're the only ones transmitting on this ++ box and since we only transmit one packet at a time we know our ++ transmit was successfull. ++ */ ++ if (txbuf) + { + dev->txbusy = 0; + break; + } +- if (txbuf) +- { +- st = efi_call_7 (net->transmit, net, 0, dev->last_pkt_size, +- dev->txbuf, NULL, NULL, NULL); +- if (st != GRUB_EFI_SUCCESS) +- return grub_error (GRUB_ERR_IO, +- N_("couldn't send network packet")); +- } + if (limit_time < grub_get_time_ms ()) + return grub_error (GRUB_ERR_TIMEOUT, + N_("couldn't send network packet")); +@@ -84,8 +84,9 @@ send_card_buffer (struct grub_net_card *dev, + we run in the GRUB_ERR_TIMEOUT case above. + Perhaps a timeout in the FW has discarded the recycle buffer. + */ ++ txbuf = NULL; + st = efi_call_3 (net->get_status, net, 0, &txbuf); +- dev->txbusy = !(st == GRUB_EFI_SUCCESS && txbuf == dev->txbuf); ++ dev->txbusy = !(st == GRUB_EFI_SUCCESS && txbuf); + + return GRUB_ERR_NONE; + } diff --git a/SOURCES/0166-Handle-rssd-storage-devices.patch b/SOURCES/0166-Handle-rssd-storage-devices.patch new file mode 100644 index 0000000..cc012e0 --- /dev/null +++ b/SOURCES/0166-Handle-rssd-storage-devices.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 30 Jun 2015 15:50:41 -0400 +Subject: [PATCH] Handle rssd storage devices. + +Resolves: rhbz#1087962 + +Signed-off-by: Peter Jones +--- + grub-core/osdep/linux/getroot.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c +index 7007193d9c7..5987d078a2f 100644 +--- a/grub-core/osdep/linux/getroot.c ++++ b/grub-core/osdep/linux/getroot.c +@@ -884,6 +884,19 @@ grub_util_part_to_disk (const char *os_dev, struct stat *st, + return path; + } + ++ /* If this is an rssd device. */ ++ if ((strncmp ("rssd", p, 4) == 0) && p[4] >= 'a' && p[4] <= 'z') ++ { ++ char *pp = p + 4; ++ while (*pp >= 'a' && *pp <= 'z') ++ pp++; ++ if (*pp) ++ *is_part = 1; ++ /* /dev/rssd[a-z]+[0-9]* */ ++ *pp = '\0'; ++ return path; ++ } ++ + /* If this is a loop device */ + if ((strncmp ("loop", p, 4) == 0) && p[4] >= '0' && p[4] <= '9') + { diff --git a/SOURCES/0167-xfs-Fix-termination-loop-for-directory-iteration.patch b/SOURCES/0167-xfs-Fix-termination-loop-for-directory-iteration.patch new file mode 100644 index 0000000..a8476c2 --- /dev/null +++ b/SOURCES/0167-xfs-Fix-termination-loop-for-directory-iteration.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Mon, 14 Jul 2014 17:21:29 +0200 +Subject: [PATCH] xfs: Fix termination loop for directory iteration + +Directory iteration used wrong position (sizeof wrong structure) for +termination of iteration inside a directory block. Luckily the position +ended up being wrong by just 1 byte and directory entries are larger so +things worked out fine in practice. But fix the problem anyway. + +Signed-off-by: Jan Kara +--- + grub-core/fs/xfs.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index 16ffd3f1ebd..4bd52d1e081 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -603,8 +603,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + - grub_be_to_cpu32 (tail->leaf_stale)); + + /* Iterate over all entries within this block. */ +- while (pos < (dirblk_size +- - (int) sizeof (struct grub_xfs_dir2_entry))) ++ while (pos < tail_start) + { + struct grub_xfs_dir2_entry *direntry; + grub_uint8_t *freetag; diff --git a/SOURCES/0168-xfs-Convert-inode-numbers-to-cpu-endianity-immediate.patch b/SOURCES/0168-xfs-Convert-inode-numbers-to-cpu-endianity-immediate.patch new file mode 100644 index 0000000..f381d9b --- /dev/null +++ b/SOURCES/0168-xfs-Convert-inode-numbers-to-cpu-endianity-immediate.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Mon, 14 Jul 2014 17:21:30 +0200 +Subject: [PATCH] xfs: Convert inode numbers to cpu endianity immediately after + reading + +Currently XFS driver converted inode numbers to native endianity only +when using them to compute inode position. Although this works, it is +somewhat confusing. So convert inode numbers when reading them from disk +structures as every other field. + +Signed-off-by: Jan Kara +--- + grub-core/fs/xfs.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index 4bd52d1e081..0d704e9a4d4 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -180,14 +180,14 @@ static inline grub_uint64_t + GRUB_XFS_INO_INOINAG (struct grub_xfs_data *data, + grub_uint64_t ino) + { +- return (grub_be_to_cpu64 (ino) & ((1LL << GRUB_XFS_INO_AGBITS (data)) - 1)); ++ return (ino & ((1LL << GRUB_XFS_INO_AGBITS (data)) - 1)); + } + + static inline grub_uint64_t + GRUB_XFS_INO_AG (struct grub_xfs_data *data, + grub_uint64_t ino) + { +- return (grub_be_to_cpu64 (ino) >> GRUB_XFS_INO_AGBITS (data)); ++ return (ino >> GRUB_XFS_INO_AGBITS (data)); + } + + static inline grub_disk_addr_t +@@ -506,13 +506,12 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + if (smallino) + { + parent = grub_be_to_cpu32 (diro->inode.data.dir.dirhead.parent.i4); +- parent = grub_cpu_to_be64 (parent); + /* The header is a bit smaller than usual. */ + de = (struct grub_xfs_dir_entry *) ((char *) de - 4); + } + else + { +- parent = diro->inode.data.dir.dirhead.parent.i8; ++ parent = grub_be_to_cpu64(diro->inode.data.dir.dirhead.parent.i8); + } + + /* Synthesize the direntries for `.' and `..'. */ +@@ -545,7 +544,6 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + | (((grub_uint64_t) inopos[5]) << 16) + | (((grub_uint64_t) inopos[6]) << 8) + | (((grub_uint64_t) inopos[7]) << 0); +- ino = grub_cpu_to_be64 (ino); + + c = de->name[de->len]; + de->name[de->len] = '\0'; +@@ -627,7 +625,8 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + is not used by GRUB. So it can be overwritten. */ + filename[direntry->len] = '\0'; + +- if (iterate_dir_call_hook (direntry->inode, filename, &ctx)) ++ if (iterate_dir_call_hook (grub_be_to_cpu64(direntry->inode), ++ filename, &ctx)) + { + grub_free (dirblock); + return 1; +@@ -689,7 +688,7 @@ grub_xfs_mount (grub_disk_t disk) + goto fail; + + data->diropen.data = data; +- data->diropen.ino = data->sblock.rootino; ++ data->diropen.ino = grub_be_to_cpu64(data->sblock.rootino); + data->diropen.inode_read = 1; + data->bsize = grub_be_to_cpu32 (data->sblock.bsize); + data->agsize = grub_be_to_cpu32 (data->sblock.agsize); diff --git a/SOURCES/0169-xfs-Add-helpers-for-inode-size.patch b/SOURCES/0169-xfs-Add-helpers-for-inode-size.patch new file mode 100644 index 0000000..ea3f241 --- /dev/null +++ b/SOURCES/0169-xfs-Add-helpers-for-inode-size.patch @@ -0,0 +1,94 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Mon, 1 Jun 2015 14:28:45 +0200 +Subject: [PATCH] xfs: Add helpers for inode size + +Add helpers to return size of XFS inode on disk and when loaded in +memory. + +Signed-off-by: Jan Kara +--- + grub-core/fs/xfs.c | 35 ++++++++++++++++++++++++----------- + 1 file changed, 24 insertions(+), 11 deletions(-) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index 0d704e9a4d4..26d8147a92e 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -255,6 +255,24 @@ grub_xfs_inode_offset (struct grub_xfs_data *data, + data->sblock.log2_inode); + } + ++static inline grub_size_t ++grub_xfs_inode_size(struct grub_xfs_data *data) ++{ ++ return 1 << data->sblock.log2_inode; ++} ++ ++/* ++ * Returns size occupied by XFS inode stored in memory - we store struct ++ * grub_fshelp_node there but on disk inode size may be actually larger than ++ * struct grub_xfs_inode so we need to account for that so that we can read ++ * from disk directly into in-memory structure. ++ */ ++static inline grub_size_t ++grub_xfs_fshelp_size(struct grub_xfs_data *data) ++{ ++ return sizeof (struct grub_fshelp_node) - sizeof (struct grub_xfs_inode) ++ + grub_xfs_inode_size(data); ++} + + static grub_err_t + grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino, +@@ -264,8 +282,8 @@ grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino, + int offset = grub_xfs_inode_offset (data, ino); + + /* Read the inode. */ +- if (grub_disk_read (data->disk, block, offset, +- 1 << data->sblock.log2_inode, inode)) ++ if (grub_disk_read (data->disk, block, offset, grub_xfs_inode_size(data), ++ inode)) + return grub_errno; + + if (grub_strncmp ((char *) inode->magic, "IN", 2)) +@@ -297,7 +315,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) + if (node->inode.fork_offset) + recoffset = (node->inode.fork_offset - 1) / 2; + else +- recoffset = ((1 << node->data->sblock.log2_inode) ++ recoffset = (grub_xfs_inode_size(node->data) + - ((char *) &node->inode.data.btree.keys + - (char *) &node->inode)) + / (2 * sizeof (grub_uint64_t)); +@@ -456,9 +474,7 @@ static int iterate_dir_call_hook (grub_uint64_t ino, const char *filename, + struct grub_fshelp_node *fdiro; + grub_err_t err; + +- fdiro = grub_malloc (sizeof (struct grub_fshelp_node) +- - sizeof (struct grub_xfs_inode) +- + (1 << ctx->diro->data->sblock.log2_inode) + 1); ++ fdiro = grub_malloc (grub_xfs_fshelp_size(ctx->diro->data) + 1); + if (!fdiro) + { + grub_print_error (); +@@ -682,7 +698,7 @@ grub_xfs_mount (grub_disk_t disk) + data = grub_realloc (data, + sizeof (struct grub_xfs_data) + - sizeof (struct grub_xfs_inode) +- + (1 << data->sblock.log2_inode) + 1); ++ + grub_xfs_inode_size(data) + 1); + + if (! data) + goto fail; +@@ -797,10 +813,7 @@ grub_xfs_open (struct grub_file *file, const char *name) + + if (fdiro != &data->diropen) + { +- grub_memcpy (&data->diropen, fdiro, +- sizeof (struct grub_fshelp_node) +- - sizeof (struct grub_xfs_inode) +- + (1 << data->sblock.log2_inode)); ++ grub_memcpy (&data->diropen, fdiro, grub_xfs_fshelp_size(data)); + grub_free (fdiro); + } + diff --git a/SOURCES/0170-xfs-V5-filesystem-format-support.patch b/SOURCES/0170-xfs-V5-filesystem-format-support.patch new file mode 100644 index 0000000..2d80632 --- /dev/null +++ b/SOURCES/0170-xfs-V5-filesystem-format-support.patch @@ -0,0 +1,576 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Mon, 1 Jun 2015 14:28:46 +0200 +Subject: [PATCH] xfs: V5 filesystem format support + +Add support for new XFS on disk format. We have to handle optional +filetype fields in directory entries, additional CRC, LSN, UUID entries +in some structures, etc. + +Signed-off-by: Jan Kara +--- + grub-core/fs/xfs.c | 332 ++++++++++++++++++++++++++++++++++++++++------------- + 1 file changed, 252 insertions(+), 80 deletions(-) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index 26d8147a92e..f00e43e7dc3 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -34,6 +34,50 @@ GRUB_MOD_LICENSE ("GPLv3+"); + #define XFS_INODE_FORMAT_EXT 2 + #define XFS_INODE_FORMAT_BTREE 3 + ++/* Superblock version field flags */ ++#define XFS_SB_VERSION_NUMBITS 0x000f ++#define XFS_SB_VERSION_ATTRBIT 0x0010 ++#define XFS_SB_VERSION_NLINKBIT 0x0020 ++#define XFS_SB_VERSION_QUOTABIT 0x0040 ++#define XFS_SB_VERSION_ALIGNBIT 0x0080 ++#define XFS_SB_VERSION_DALIGNBIT 0x0100 ++#define XFS_SB_VERSION_LOGV2BIT 0x0400 ++#define XFS_SB_VERSION_SECTORBIT 0x0800 ++#define XFS_SB_VERSION_EXTFLGBIT 0x1000 ++#define XFS_SB_VERSION_DIRV2BIT 0x2000 ++#define XFS_SB_VERSION_MOREBITSBIT 0x8000 ++#define XFS_SB_VERSION_BITS_SUPPORTED \ ++ (XFS_SB_VERSION_NUMBITS | \ ++ XFS_SB_VERSION_ATTRBIT | \ ++ XFS_SB_VERSION_NLINKBIT | \ ++ XFS_SB_VERSION_QUOTABIT | \ ++ XFS_SB_VERSION_ALIGNBIT | \ ++ XFS_SB_VERSION_DALIGNBIT | \ ++ XFS_SB_VERSION_LOGV2BIT | \ ++ XFS_SB_VERSION_SECTORBIT | \ ++ XFS_SB_VERSION_EXTFLGBIT | \ ++ XFS_SB_VERSION_DIRV2BIT | \ ++ XFS_SB_VERSION_MOREBITSBIT) ++ ++/* Recognized xfs format versions */ ++#define XFS_SB_VERSION_4 4 /* Good old XFS filesystem */ ++#define XFS_SB_VERSION_5 5 /* CRC enabled filesystem */ ++ ++/* features2 field flags */ ++#define XFS_SB_VERSION2_LAZYSBCOUNTBIT 0x00000002 /* Superblk counters */ ++#define XFS_SB_VERSION2_ATTR2BIT 0x00000008 /* Inline attr rework */ ++#define XFS_SB_VERSION2_PROJID32BIT 0x00000080 /* 32-bit project ids */ ++#define XFS_SB_VERSION2_FTYPE 0x00000200 /* inode type in dir */ ++#define XFS_SB_VERSION2_BITS_SUPPORTED \ ++ (XFS_SB_VERSION2_LAZYSBCOUNTBIT | \ ++ XFS_SB_VERSION2_ATTR2BIT | \ ++ XFS_SB_VERSION2_PROJID32BIT | \ ++ XFS_SB_VERSION2_FTYPE) ++ ++/* incompat feature flags */ ++#define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */ ++#define XFS_SB_FEAT_INCOMPAT_SUPPORTED \ ++ (XFS_SB_FEAT_INCOMPAT_FTYPE) + + struct grub_xfs_sblock + { +@@ -45,7 +89,9 @@ struct grub_xfs_sblock + grub_uint64_t rootino; + grub_uint8_t unused3[20]; + grub_uint32_t agsize; +- grub_uint8_t unused4[20]; ++ grub_uint8_t unused4[12]; ++ grub_uint16_t version; ++ grub_uint8_t unused5[6]; + grub_uint8_t label[12]; + grub_uint8_t log2_bsize; + grub_uint8_t log2_sect; +@@ -54,12 +100,19 @@ struct grub_xfs_sblock + grub_uint8_t log2_agblk; + grub_uint8_t unused6[67]; + grub_uint8_t log2_dirblk; ++ grub_uint8_t unused7[7]; ++ grub_uint32_t features2; ++ grub_uint8_t unused8[4]; ++ grub_uint32_t sb_features_compat; ++ grub_uint32_t sb_features_ro_compat; ++ grub_uint32_t sb_features_incompat; ++ grub_uint32_t sb_features_log_incompat; + } GRUB_PACKED; + + struct grub_xfs_dir_header + { + grub_uint8_t count; +- grub_uint8_t smallino; ++ grub_uint8_t largeino; + union + { + grub_uint32_t i4; +@@ -67,14 +120,16 @@ struct grub_xfs_dir_header + } GRUB_PACKED parent; + } GRUB_PACKED; + ++/* Structure for directory entry inlined in the inode */ + struct grub_xfs_dir_entry + { + grub_uint8_t len; + grub_uint16_t offset; + char name[1]; +- /* Inode number follows, 32 bits. */ ++ /* Inode number follows, 32 / 64 bits. */ + } GRUB_PACKED; + ++/* Structure for directory entry in a block */ + struct grub_xfs_dir2_entry + { + grub_uint64_t inode; +@@ -90,7 +145,8 @@ struct grub_xfs_btree_node + grub_uint16_t numrecs; + grub_uint64_t left; + grub_uint64_t right; +- grub_uint64_t keys[1]; ++ /* In V5 here follow crc, uuid, etc. */ ++ /* Then follow keys and block pointers */ + } GRUB_PACKED; + + struct grub_xfs_btree_root +@@ -123,19 +179,11 @@ struct grub_xfs_inode + grub_uint16_t unused3; + grub_uint8_t fork_offset; + grub_uint8_t unused4[17]; +- union +- { +- char raw[156]; +- struct dir +- { +- struct grub_xfs_dir_header dirhead; +- struct grub_xfs_dir_entry direntry[1]; +- } dir; +- grub_xfs_extent extents[XFS_INODE_EXTENTS]; +- struct grub_xfs_btree_root btree; +- } GRUB_PACKED data; + } GRUB_PACKED; + ++#define XFS_V2_INODE_SIZE sizeof(struct grub_xfs_inode) ++#define XFS_V3_INODE_SIZE (XFS_V2_INODE_SIZE + 76) ++ + struct grub_xfs_dirblock_tail + { + grub_uint32_t leaf_count; +@@ -157,6 +205,8 @@ struct grub_xfs_data + int pos; + int bsize; + grub_uint32_t agsize; ++ unsigned int hasftype:1; ++ unsigned int hascrc:1; + struct grub_fshelp_node diropen; + }; + +@@ -164,6 +214,71 @@ static grub_dl_t my_mod; + + + ++static int grub_xfs_sb_hascrc(struct grub_xfs_data *data) ++{ ++ return (data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_NUMBITS)) == ++ grub_cpu_to_be16_compile_time(XFS_SB_VERSION_5); ++} ++ ++static int grub_xfs_sb_hasftype(struct grub_xfs_data *data) ++{ ++ if ((data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_NUMBITS)) == ++ grub_cpu_to_be16_compile_time(XFS_SB_VERSION_5) && ++ data->sblock.sb_features_incompat & grub_cpu_to_be32_compile_time(XFS_SB_FEAT_INCOMPAT_FTYPE)) ++ return 1; ++ if (data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_MOREBITSBIT) && ++ data->sblock.features2 & grub_cpu_to_be32_compile_time(XFS_SB_VERSION2_FTYPE)) ++ return 1; ++ return 0; ++} ++ ++static int grub_xfs_sb_valid(struct grub_xfs_data *data) ++{ ++ grub_dprintf("xfs", "Validating superblock\n"); ++ if (grub_strncmp ((char *) (data->sblock.magic), "XFSB", 4) ++ || data->sblock.log2_bsize < GRUB_DISK_SECTOR_BITS ++ || ((int) data->sblock.log2_bsize ++ + (int) data->sblock.log2_dirblk) >= 27) ++ { ++ grub_error (GRUB_ERR_BAD_FS, "not a XFS filesystem"); ++ return 0; ++ } ++ if ((data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_NUMBITS)) == ++ grub_cpu_to_be16_compile_time(XFS_SB_VERSION_5)) ++ { ++ grub_dprintf("xfs", "XFS v5 superblock detected\n"); ++ if (data->sblock.sb_features_incompat & ++ grub_cpu_to_be32_compile_time(~XFS_SB_FEAT_INCOMPAT_SUPPORTED)) ++ { ++ grub_error (GRUB_ERR_BAD_FS, "XFS filesystem has unsupported " ++ "incompatible features"); ++ return 0; ++ } ++ return 1; ++ } ++ else if ((data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_NUMBITS)) == ++ grub_cpu_to_be16_compile_time(XFS_SB_VERSION_4)) ++ { ++ grub_dprintf("xfs", "XFS v4 superblock detected\n"); ++ if (!(data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_DIRV2BIT))) ++ { ++ grub_error (GRUB_ERR_BAD_FS, "XFS filesystem without V2 directories " ++ "is unsupported"); ++ return 0; ++ } ++ if (data->sblock.version & grub_cpu_to_be16_compile_time(~XFS_SB_VERSION_BITS_SUPPORTED) || ++ (data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_MOREBITSBIT) && ++ data->sblock.features2 & grub_cpu_to_be16_compile_time(~XFS_SB_VERSION2_BITS_SUPPORTED))) ++ { ++ grub_error (GRUB_ERR_BAD_FS, "XFS filesystem has unsupported version " ++ "bits"); ++ return 0; ++ } ++ return 1; ++ } ++ return 0; ++} ++ + /* Filetype information as used in inodes. */ + #define FILETYPE_INO_MASK 0170000 + #define FILETYPE_INO_REG 0100000 +@@ -219,18 +334,6 @@ GRUB_XFS_EXTENT_SIZE (grub_xfs_extent *exts, int ex) + return (grub_be_to_cpu32 (exts[ex][3]) & ((1 << 21) - 1)); + } + +-static inline int +-GRUB_XFS_ROUND_TO_DIRENT (int pos) +-{ +- return ((((pos) + 8 - 1) / 8) * 8); +-} +- +-static inline int +-GRUB_XFS_NEXT_DIRENT (int pos, int len) +-{ +- return (pos) + GRUB_XFS_ROUND_TO_DIRENT (8 + 1 + len + 2); +-} +- + + static inline grub_uint64_t + grub_xfs_inode_block (struct grub_xfs_data *data, +@@ -274,6 +377,85 @@ grub_xfs_fshelp_size(struct grub_xfs_data *data) + + grub_xfs_inode_size(data); + } + ++static void * ++grub_xfs_inode_data(struct grub_xfs_inode *inode) ++{ ++ if (inode->version <= 2) ++ return ((char *)inode) + XFS_V2_INODE_SIZE; ++ return ((char *)inode) + XFS_V3_INODE_SIZE; ++} ++ ++static struct grub_xfs_dir_entry * ++grub_xfs_inline_de(struct grub_xfs_dir_header *head) ++{ ++ /* ++ * With small inode numbers the header is 4 bytes smaller because of ++ * smaller parent pointer ++ */ ++ return (void *)(((char *)head) + sizeof(struct grub_xfs_dir_header) - ++ (head->largeino ? 0 : sizeof(grub_uint32_t))); ++} ++ ++static grub_uint8_t * ++grub_xfs_inline_de_inopos(struct grub_xfs_data *data, ++ struct grub_xfs_dir_entry *de) ++{ ++ return ((grub_uint8_t *)(de + 1)) + de->len - 1 + ++ (data->hasftype ? 1 : 0); ++} ++ ++static struct grub_xfs_dir_entry * ++grub_xfs_inline_next_de(struct grub_xfs_data *data, ++ struct grub_xfs_dir_header *head, ++ struct grub_xfs_dir_entry *de) ++{ ++ char *p = (char *)de + sizeof(struct grub_xfs_dir_entry) - 1 + de->len; ++ ++ p += head->largeino ? sizeof(grub_uint64_t) : sizeof(grub_uint32_t); ++ if (data->hasftype) ++ p++; ++ ++ return (struct grub_xfs_dir_entry *)p; ++} ++ ++static struct grub_xfs_dirblock_tail * ++grub_xfs_dir_tail(struct grub_xfs_data *data, void *dirblock) ++{ ++ int dirblksize = 1 << (data->sblock.log2_bsize + data->sblock.log2_dirblk); ++ ++ return (struct grub_xfs_dirblock_tail *) ++ ((char *)dirblock + dirblksize - sizeof (struct grub_xfs_dirblock_tail)); ++} ++ ++static struct grub_xfs_dir2_entry * ++grub_xfs_first_de(struct grub_xfs_data *data, void *dirblock) ++{ ++ if (data->hascrc) ++ return (struct grub_xfs_dir2_entry *)((char *)dirblock + 64); ++ return (struct grub_xfs_dir2_entry *)((char *)dirblock + 16); ++} ++ ++static struct grub_xfs_dir2_entry * ++grub_xfs_next_de(struct grub_xfs_data *data, struct grub_xfs_dir2_entry *de) ++{ ++ int size = sizeof (struct grub_xfs_dir2_entry) + de->len + 2 /* Tag */; ++ ++ if (data->hasftype) ++ size++; /* File type */ ++ return (struct grub_xfs_dir2_entry *)(((char *)de) + ALIGN_UP(size, 8)); ++} ++ ++static grub_uint64_t * ++grub_xfs_btree_keys(struct grub_xfs_data *data, ++ struct grub_xfs_btree_node *leaf) ++{ ++ grub_uint64_t *keys = (grub_uint64_t *)(leaf + 1); ++ ++ if (data->hascrc) ++ keys += 6; /* skip crc, uuid, ... */ ++ return keys; ++} ++ + static grub_err_t + grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino, + struct grub_xfs_inode *inode) +@@ -281,6 +463,8 @@ grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino, + grub_uint64_t block = grub_xfs_inode_block (data, ino); + int offset = grub_xfs_inode_offset (data, ino); + ++ grub_dprintf("xfs", "Reading inode (%"PRIuGRUB_UINT64_T") - %"PRIuGRUB_UINT64_T", %d\n", ++ ino, block, offset); + /* Read the inode. */ + if (grub_disk_read (data->disk, block, offset, grub_xfs_inode_size(data), + inode)) +@@ -303,6 +487,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) + + if (node->inode.format == XFS_INODE_FORMAT_BTREE) + { ++ struct grub_xfs_btree_root *root; + const grub_uint64_t *keys; + int recoffset; + +@@ -310,15 +495,15 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) + if (leaf == 0) + return 0; + +- nrec = grub_be_to_cpu16 (node->inode.data.btree.numrecs); +- keys = &node->inode.data.btree.keys[0]; ++ root = grub_xfs_inode_data(&node->inode); ++ nrec = grub_be_to_cpu16 (root->numrecs); ++ keys = &root->keys[0]; + if (node->inode.fork_offset) + recoffset = (node->inode.fork_offset - 1) / 2; + else + recoffset = (grub_xfs_inode_size(node->data) +- - ((char *) &node->inode.data.btree.keys +- - (char *) &node->inode)) +- / (2 * sizeof (grub_uint64_t)); ++ - ((char *) keys - (char *) &node->inode)) ++ / (2 * sizeof (grub_uint64_t)); + do + { + int i; +@@ -340,7 +525,10 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) + 0, node->data->bsize, leaf)) + return 0; + +- if (grub_strncmp ((char *) leaf->magic, "BMAP", 4)) ++ if ((!node->data->hascrc && ++ grub_strncmp ((char *) leaf->magic, "BMAP", 4)) || ++ (node->data->hascrc && ++ grub_strncmp ((char *) leaf->magic, "BMA3", 4))) + { + grub_free (leaf); + grub_error (GRUB_ERR_BAD_FS, "not a correct XFS BMAP node"); +@@ -348,8 +536,8 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) + } + + nrec = grub_be_to_cpu16 (leaf->numrecs); +- keys = &leaf->keys[0]; +- recoffset = ((node->data->bsize - ((char *) &leaf->keys ++ keys = grub_xfs_btree_keys(node->data, leaf); ++ recoffset = ((node->data->bsize - ((char *) keys + - (char *) leaf)) + / (2 * sizeof (grub_uint64_t))); + } +@@ -359,7 +547,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) + else if (node->inode.format == XFS_INODE_FORMAT_EXT) + { + nrec = grub_be_to_cpu32 (node->inode.nextents); +- exts = &node->inode.data.extents[0]; ++ exts = grub_xfs_inode_data(&node->inode); + } + else + { +@@ -417,7 +605,7 @@ grub_xfs_read_symlink (grub_fshelp_node_t node) + switch (node->inode.format) + { + case XFS_INODE_FORMAT_INO: +- return grub_strndup (node->inode.data.raw, size); ++ return grub_strndup (grub_xfs_inode_data(&node->inode), size); + + case XFS_INODE_FORMAT_EXT: + { +@@ -512,23 +700,18 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + { + case XFS_INODE_FORMAT_INO: + { +- struct grub_xfs_dir_entry *de = &diro->inode.data.dir.direntry[0]; +- int smallino = !diro->inode.data.dir.dirhead.smallino; ++ struct grub_xfs_dir_header *head = grub_xfs_inode_data(&diro->inode); ++ struct grub_xfs_dir_entry *de = grub_xfs_inline_de(head); ++ int smallino = !head->largeino; + int i; + grub_uint64_t parent; + + /* If small inode numbers are used to pack the direntry, the + parent inode number is small too. */ + if (smallino) +- { +- parent = grub_be_to_cpu32 (diro->inode.data.dir.dirhead.parent.i4); +- /* The header is a bit smaller than usual. */ +- de = (struct grub_xfs_dir_entry *) ((char *) de - 4); +- } ++ parent = grub_be_to_cpu32 (head->parent.i4); + else +- { +- parent = grub_be_to_cpu64(diro->inode.data.dir.dirhead.parent.i8); +- } ++ parent = grub_be_to_cpu64 (head->parent.i8); + + /* Synthesize the direntries for `.' and `..'. */ + if (iterate_dir_call_hook (diro->ino, ".", &ctx)) +@@ -537,12 +720,10 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + if (iterate_dir_call_hook (parent, "..", &ctx)) + return 1; + +- for (i = 0; i < diro->inode.data.dir.dirhead.count; i++) ++ for (i = 0; i < head->count; i++) + { + grub_uint64_t ino; +- grub_uint8_t *inopos = (((grub_uint8_t *) de) +- + sizeof (struct grub_xfs_dir_entry) +- + de->len - 1); ++ grub_uint8_t *inopos = grub_xfs_inline_de_inopos(dir->data, de); + grub_uint8_t c; + + /* inopos might be unaligned. */ +@@ -567,10 +748,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + return 1; + de->name[de->len] = c; + +- de = ((struct grub_xfs_dir_entry *) +- (((char *) de)+ sizeof (struct grub_xfs_dir_entry) + de->len +- + ((smallino ? sizeof (grub_uint32_t) +- : sizeof (grub_uint64_t))) - 1)); ++ de = grub_xfs_inline_next_de(dir->data, head, de); + } + break; + } +@@ -597,15 +775,11 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + >> dirblk_log2); + blk++) + { +- /* The header is skipped, the first direntry is stored +- from byte 16. */ +- int pos = 16; ++ struct grub_xfs_dir2_entry *direntry = ++ grub_xfs_first_de(dir->data, dirblock); + int entries; +- int tail_start = (dirblk_size +- - sizeof (struct grub_xfs_dirblock_tail)); +- +- struct grub_xfs_dirblock_tail *tail; +- tail = (struct grub_xfs_dirblock_tail *) &dirblock[tail_start]; ++ struct grub_xfs_dirblock_tail *tail = ++ grub_xfs_dir_tail(dir->data, dirblock); + + numread = grub_xfs_read_file (dir, 0, 0, + blk << dirblk_log2, +@@ -617,13 +791,11 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + - grub_be_to_cpu32 (tail->leaf_stale)); + + /* Iterate over all entries within this block. */ +- while (pos < tail_start) ++ while ((char *)direntry < (char *)tail) + { +- struct grub_xfs_dir2_entry *direntry; + grub_uint8_t *freetag; + char *filename; + +- direntry = (struct grub_xfs_dir2_entry *) &dirblock[pos]; + freetag = (grub_uint8_t *) direntry; + + if (grub_get_unaligned16 (freetag) == 0XFFFF) +@@ -631,14 +803,16 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + grub_uint8_t *skip = (freetag + sizeof (grub_uint16_t)); + + /* This entry is not used, go to the next one. */ +- pos += grub_be_to_cpu16 (grub_get_unaligned16 (skip)); ++ direntry = (struct grub_xfs_dir2_entry *) ++ (((char *)direntry) + ++ grub_be_to_cpu16 (grub_get_unaligned16 (skip))); + + continue; + } + +- filename = &dirblock[pos + sizeof (*direntry)]; +- /* The byte after the filename is for the tag, which +- is not used by GRUB. So it can be overwritten. */ ++ filename = (char *)(direntry + 1); ++ /* The byte after the filename is for the filetype, padding, or ++ tag, which is not used by GRUB. So it can be overwritten. */ + filename[direntry->len] = '\0'; + + if (iterate_dir_call_hook (grub_be_to_cpu64(direntry->inode), +@@ -655,8 +829,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + break; + + /* Select the next directory entry. */ +- pos = GRUB_XFS_NEXT_DIRENT (pos, direntry->len); +- pos = GRUB_XFS_ROUND_TO_DIRENT (pos); ++ direntry = grub_xfs_next_de(dir->data, direntry); + } + } + grub_free (dirblock); +@@ -681,19 +854,14 @@ grub_xfs_mount (grub_disk_t disk) + if (!data) + return 0; + ++ grub_dprintf("xfs", "Reading sb\n"); + /* Read the superblock. */ + if (grub_disk_read (disk, 0, 0, + sizeof (struct grub_xfs_sblock), &data->sblock)) + goto fail; + +- if (grub_strncmp ((char *) (data->sblock.magic), "XFSB", 4) +- || data->sblock.log2_bsize < GRUB_DISK_SECTOR_BITS +- || ((int) data->sblock.log2_bsize +- + (int) data->sblock.log2_dirblk) >= 27) +- { +- grub_error (GRUB_ERR_BAD_FS, "not a XFS filesystem"); +- goto fail; +- } ++ if (!grub_xfs_sb_valid(data)) ++ goto fail; + + data = grub_realloc (data, + sizeof (struct grub_xfs_data) +@@ -708,9 +876,13 @@ grub_xfs_mount (grub_disk_t disk) + data->diropen.inode_read = 1; + data->bsize = grub_be_to_cpu32 (data->sblock.bsize); + data->agsize = grub_be_to_cpu32 (data->sblock.agsize); ++ data->hasftype = grub_xfs_sb_hasftype(data); ++ data->hascrc = grub_xfs_sb_hascrc(data); + + data->disk = disk; + data->pos = 0; ++ grub_dprintf("xfs", "Reading root ino %"PRIuGRUB_UINT64_T"\n", ++ grub_cpu_to_be64(data->sblock.rootino)); + + grub_xfs_read_inode (data, data->diropen.ino, &data->diropen.inode); + diff --git a/SOURCES/0171-xfs-silence-Coverity-overflow-warning.patch b/SOURCES/0171-xfs-silence-Coverity-overflow-warning.patch new file mode 100644 index 0000000..b65a692 --- /dev/null +++ b/SOURCES/0171-xfs-silence-Coverity-overflow-warning.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Fri, 19 Jun 2015 18:38:25 +0300 +Subject: [PATCH] xfs: silence Coverity overflow warning + +inode size cannot really overflow integer, but Coverity does not know it. +CID: 96602 +--- + grub-core/fs/xfs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index f00e43e7dc3..72492915533 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -361,7 +361,7 @@ grub_xfs_inode_offset (struct grub_xfs_data *data, + static inline grub_size_t + grub_xfs_inode_size(struct grub_xfs_data *data) + { +- return 1 << data->sblock.log2_inode; ++ return (grub_size_t)1 << data->sblock.log2_inode; + } + + /* diff --git a/SOURCES/0172-send-router-solicitation-for-ipv6-address-autoconf-v.patch b/SOURCES/0172-send-router-solicitation-for-ipv6-address-autoconf-v.patch new file mode 100644 index 0000000..332a464 --- /dev/null +++ b/SOURCES/0172-send-router-solicitation-for-ipv6-address-autoconf-v.patch @@ -0,0 +1,160 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Tue, 18 Nov 2014 16:03:08 +0800 +Subject: [PATCH] send router solicitation for ipv6 address autoconf v2 + +Many routers have long router advertisment interval configured by +default. The Neighbor Discovery protocol (RFC4861) has defined default +MaxRtrAdvInterval value as 600 seconds and +MinRtrAdvInterval as 0.33*MaxRtrAdvInterval. This makes +net_ipv6_autoconf fails more often than not as currently it passively +listens the RA message to perfom address autoconfiguration. + +This patch tries to send router solicitation to overcome the problem of +long RA interval. + +v2: +use cpu_to_be macro for network byte order conversion +add missing error handling +--- + grub-core/net/icmp6.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++ + grub-core/net/net.c | 4 ++- + include/grub/net/ip.h | 2 ++ + 3 files changed, 88 insertions(+), 1 deletion(-) + +diff --git a/grub-core/net/icmp6.c b/grub-core/net/icmp6.c +index bbc902014fe..0843a15afda 100644 +--- a/grub-core/net/icmp6.c ++++ b/grub-core/net/icmp6.c +@@ -72,6 +72,11 @@ struct neighbour_advertise + grub_uint64_t target[2]; + } GRUB_PACKED; + ++struct router_solicit ++{ ++ grub_uint32_t reserved; ++} GRUB_PACKED; ++ + enum + { + FLAG_SLAAC = 0x40 +@@ -81,6 +86,7 @@ enum + { + ICMP6_ECHO = 128, + ICMP6_ECHO_REPLY = 129, ++ ICMP6_ROUTER_SOLICIT = 133, + ICMP6_ROUTER_ADVERTISE = 134, + ICMP6_NEIGHBOUR_SOLICIT = 135, + ICMP6_NEIGHBOUR_ADVERTISE = 136, +@@ -533,3 +539,80 @@ grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf, + grub_netbuff_free (nb); + return err; + } ++ ++grub_err_t ++grub_net_icmp6_send_router_solicit (struct grub_net_network_level_interface *inf) ++{ ++ struct grub_net_buff *nb; ++ grub_err_t err = GRUB_ERR_NONE; ++ grub_net_network_level_address_t multicast; ++ grub_net_link_level_address_t ll_multicast; ++ struct option_header *ohdr; ++ struct router_solicit *sol; ++ struct icmp_header *icmphr; ++ ++ multicast.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; ++ multicast.ipv6[0] = grub_cpu_to_be64 (0xff02ULL << 48); ++ multicast.ipv6[1] = grub_cpu_to_be64 (0x02ULL); ++ ++ err = grub_net_link_layer_resolve (inf, &multicast, &ll_multicast); ++ if (err) ++ return err; ++ ++ nb = grub_netbuff_alloc (sizeof (struct router_solicit) ++ + sizeof (struct option_header) ++ + 6 ++ + sizeof (struct icmp_header) ++ + GRUB_NET_OUR_IPV6_HEADER_SIZE ++ + GRUB_NET_MAX_LINK_HEADER_SIZE); ++ if (!nb) ++ return grub_errno; ++ err = grub_netbuff_reserve (nb, ++ sizeof (struct router_solicit) ++ + sizeof (struct option_header) ++ + 6 ++ + sizeof (struct icmp_header) ++ + GRUB_NET_OUR_IPV6_HEADER_SIZE ++ + GRUB_NET_MAX_LINK_HEADER_SIZE); ++ if (err) ++ goto fail; ++ ++ err = grub_netbuff_push (nb, 6); ++ if (err) ++ goto fail; ++ ++ grub_memcpy (nb->data, inf->hwaddress.mac, 6); ++ ++ err = grub_netbuff_push (nb, sizeof (*ohdr)); ++ if (err) ++ goto fail; ++ ++ ohdr = (struct option_header *) nb->data; ++ ohdr->type = OPTION_SOURCE_LINK_LAYER_ADDRESS; ++ ohdr->len = 1; ++ ++ err = grub_netbuff_push (nb, sizeof (*sol)); ++ if (err) ++ goto fail; ++ ++ sol = (struct router_solicit *) nb->data; ++ sol->reserved = 0; ++ ++ err = grub_netbuff_push (nb, sizeof (*icmphr)); ++ if (err) ++ goto fail; ++ ++ icmphr = (struct icmp_header *) nb->data; ++ icmphr->type = ICMP6_ROUTER_SOLICIT; ++ icmphr->code = 0; ++ icmphr->checksum = 0; ++ icmphr->checksum = grub_net_ip_transport_checksum (nb, ++ GRUB_NET_IP_ICMPV6, ++ &inf->address, ++ &multicast); ++ err = grub_net_send_ip_packet (inf, &multicast, &ll_multicast, nb, ++ GRUB_NET_IP_ICMPV6); ++ fail: ++ grub_netbuff_free (nb); ++ return err; ++} +diff --git a/grub-core/net/net.c b/grub-core/net/net.c +index 10bfed31b2b..b10addbe27b 100644 +--- a/grub-core/net/net.c ++++ b/grub-core/net/net.c +@@ -380,12 +380,14 @@ grub_cmd_ipv6_autoconf (struct grub_command *cmd __attribute__ ((unused)), + + for (interval = 200; interval < 10000; interval *= 2) + { +- /* FIXME: send router solicitation. */ + int done = 1; + for (j = 0; j < ncards; j++) + { + if (slaacs[j]->slaac_counter) + continue; ++ err = grub_net_icmp6_send_router_solicit (ifaces[j]); ++ if (err) ++ err = GRUB_ERR_NONE; + done = 0; + } + if (done) +diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h +index 7a8e614794d..dcceaa56894 100644 +--- a/include/grub/net/ip.h ++++ b/include/grub/net/ip.h +@@ -92,4 +92,6 @@ grub_err_t + grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *proto_addr); + ++grub_err_t ++grub_net_icmp6_send_router_solicit (struct grub_net_network_level_interface *inf); + #endif diff --git a/SOURCES/0173-icmp6-fix-no-respond-to-neighbor-solicit-message.patch b/SOURCES/0173-icmp6-fix-no-respond-to-neighbor-solicit-message.patch new file mode 100644 index 0000000..0968619 --- /dev/null +++ b/SOURCES/0173-icmp6-fix-no-respond-to-neighbor-solicit-message.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Mon, 3 Nov 2014 16:27:45 +0800 +Subject: [PATCH] icmp6 fix no respond to neighbor solicit message + +The structure size used in grub_netbuff_pull to get the pointer to +option header is apparently wrong, which leads to subsequent range check +failed and therefore not responding to any neighbor solicit message in my +testing. +--- + grub-core/net/icmp6.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/net/icmp6.c b/grub-core/net/icmp6.c +index 0843a15afda..78223946031 100644 +--- a/grub-core/net/icmp6.c ++++ b/grub-core/net/icmp6.c +@@ -211,7 +211,7 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb, + if (ttl != 0xff) + break; + nbh = (struct neighbour_solicit *) nb->data; +- err = grub_netbuff_pull (nb, sizeof (struct router_adv)); ++ err = grub_netbuff_pull (nb, sizeof (*nbh)); + if (err) + { + grub_netbuff_free (nb); diff --git a/SOURCES/0174-calibrate_tsc-use-the-Stall-EFI-boot-service-on-GRUB.patch b/SOURCES/0174-calibrate_tsc-use-the-Stall-EFI-boot-service-on-GRUB.patch new file mode 100644 index 0000000..defe185 --- /dev/null +++ b/SOURCES/0174-calibrate_tsc-use-the-Stall-EFI-boot-service-on-GRUB.patch @@ -0,0 +1,70 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Fri, 10 Oct 2014 11:11:09 +0200 +Subject: [PATCH] calibrate_tsc(): use the Stall() EFI boot service on + GRUB_MACHINE_EFI + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1150698 + +HyperV Gen2 virtual machines have no PIT; guest code should rely on UEFI +services instead. + +Signed-off-by: RHEL Ninjas +--- + grub-core/kern/i386/tsc.c | 20 ++++++++++++++++---- + 1 file changed, 16 insertions(+), 4 deletions(-) + +diff --git a/grub-core/kern/i386/tsc.c b/grub-core/kern/i386/tsc.c +index 3a4cae601d0..e49964833ca 100644 +--- a/grub-core/kern/i386/tsc.c ++++ b/grub-core/kern/i386/tsc.c +@@ -26,9 +26,14 @@ + #include + #include + #ifdef GRUB_MACHINE_XEN +-#include ++# include + #else +-#include ++# ifdef GRUB_MACHINE_EFI ++# include ++# include ++# else ++# include ++# endif + #endif + #include + +@@ -72,8 +77,14 @@ grub_cpu_is_tsc_supported (void) + #ifndef GRUB_MACHINE_XEN + + static void +-grub_pit_wait (grub_uint16_t tics) ++grub_stall (grub_uint16_t tics) + { ++# ifdef GRUB_MACHINE_EFI ++ grub_uint64_t microseconds; ++ ++ microseconds = (grub_uint64_t)tics * 1000 * 1000 * 3 / 3579545; ++ efi_call_1 (grub_efi_system_table->boot_services->stall, microseconds); ++# else + /* Disable timer2 gate and speaker. */ + grub_outb (grub_inb (GRUB_PIT_SPEAKER_PORT) + & ~ (GRUB_PIT_SPK_DATA | GRUB_PIT_SPK_TMR2), +@@ -97,6 +108,7 @@ grub_pit_wait (grub_uint16_t tics) + grub_outb (grub_inb (GRUB_PIT_SPEAKER_PORT) + & ~ (GRUB_PIT_SPK_DATA | GRUB_PIT_SPK_TMR2), + GRUB_PIT_SPEAKER_PORT); ++# endif + } + #endif + +@@ -119,7 +131,7 @@ calibrate_tsc (void) + grub_uint64_t end_tsc; + + tsc_boot_time = grub_get_tsc (); +- grub_pit_wait (0xffff); ++ grub_stall (0xffff); + end_tsc = grub_get_tsc (); + + grub_tsc_rate = grub_divmod64 ((55ULL << 32), end_tsc - tsc_boot_time, 0); diff --git a/SOURCES/0175-fix-memory-corruption-in-pubkey-filter-over-network.patch b/SOURCES/0175-fix-memory-corruption-in-pubkey-filter-over-network.patch new file mode 100644 index 0000000..0b95ffe --- /dev/null +++ b/SOURCES/0175-fix-memory-corruption-in-pubkey-filter-over-network.patch @@ -0,0 +1,164 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Fri, 5 Dec 2014 21:17:08 +0300 +Subject: [PATCH] fix memory corruption in pubkey filter over network + +grub_pubkey_open closed original file after it was read; it set +io->device to NULL to prevent grub_file_close from trying to close device. +But network device itself is stacked (net -> bufio); and bufio preserved +original netfs file which hold reference to device. grub_file_close(io) +called grub_bufio_close which called grub_file_close for original file. +grub_file_close(netfs-file) now also called grub_device_close which +freed file->device->net. So file structure returned by grub_pubkey_open +now had device->net pointed to freed memory. When later file was closed, +it was attempted to be freed again. + +Change grub_pubkey_open to behave like other filters - preserve original +parent file and pass grub_file_close down to parent. In this way only the +original file will close device. We really need to move this logic into +core instead. + +Also plug memory leaks in error paths on the way. + +Reported-By: Robert Kliewer +Closes: bug #43601 +--- + grub-core/commands/verify.c | 72 +++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 60 insertions(+), 12 deletions(-) + +diff --git a/grub-core/commands/verify.c b/grub-core/commands/verify.c +index 525bdd18737..d5995766b4c 100644 +--- a/grub-core/commands/verify.c ++++ b/grub-core/commands/verify.c +@@ -33,6 +33,13 @@ + + GRUB_MOD_LICENSE ("GPLv3+"); + ++struct grub_verified ++{ ++ grub_file_t file; ++ void *buf; ++}; ++typedef struct grub_verified *grub_verified_t; ++ + enum + { + OPTION_SKIP_SIG = 0 +@@ -802,19 +809,39 @@ grub_cmd_verify_signature (grub_extcmd_context_t ctxt, + + static int sec = 0; + ++static void ++verified_free (grub_verified_t verified) ++{ ++ if (verified) ++ { ++ grub_free (verified->buf); ++ grub_free (verified); ++ } ++} ++ + static grub_ssize_t + verified_read (struct grub_file *file, char *buf, grub_size_t len) + { +- grub_memcpy (buf, (char *) file->data + file->offset, len); ++ grub_verified_t verified = file->data; ++ ++ grub_memcpy (buf, (char *) verified->buf + file->offset, len); + return len; + } + + static grub_err_t + verified_close (struct grub_file *file) + { +- grub_free (file->data); ++ grub_verified_t verified = file->data; ++ ++ grub_file_close (verified->file); ++ verified_free (verified); + file->data = 0; +- return GRUB_ERR_NONE; ++ ++ /* device and name are freed by parent */ ++ file->device = 0; ++ file->name = 0; ++ ++ return grub_errno; + } + + struct grub_fs verified_fs = +@@ -832,6 +859,7 @@ grub_pubkey_open (grub_file_t io, const char *filename) + grub_err_t err; + grub_file_filter_t curfilt[GRUB_FILE_FILTER_MAX]; + grub_file_t ret; ++ grub_verified_t verified; + + if (!sec) + return io; +@@ -857,7 +885,10 @@ grub_pubkey_open (grub_file_t io, const char *filename) + + ret = grub_malloc (sizeof (*ret)); + if (!ret) +- return NULL; ++ { ++ grub_file_close (sig); ++ return NULL; ++ } + *ret = *io; + + ret->fs = &verified_fs; +@@ -866,29 +897,46 @@ grub_pubkey_open (grub_file_t io, const char *filename) + { + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "big file signature isn't implemented yet"); ++ grub_file_close (sig); ++ grub_free (ret); ++ return NULL; ++ } ++ verified = grub_malloc (sizeof (*verified)); ++ if (!verified) ++ { ++ grub_file_close (sig); ++ grub_free (ret); + return NULL; + } +- ret->data = grub_malloc (ret->size); +- if (!ret->data) ++ verified->buf = grub_malloc (ret->size); ++ if (!verified->buf) + { ++ grub_file_close (sig); ++ grub_free (verified); + grub_free (ret); + return NULL; + } +- if (grub_file_read (io, ret->data, ret->size) != (grub_ssize_t) ret->size) ++ if (grub_file_read (io, verified->buf, ret->size) != (grub_ssize_t) ret->size) + { + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + filename); ++ grub_file_close (sig); ++ verified_free (verified); ++ grub_free (ret); + return NULL; + } + +- err = grub_verify_signature_real (ret->data, ret->size, 0, sig, NULL); ++ err = grub_verify_signature_real (verified->buf, ret->size, 0, sig, NULL); + grub_file_close (sig); + if (err) +- return NULL; +- io->device = 0; +- io->name = 0; +- grub_file_close (io); ++ { ++ verified_free (verified); ++ grub_free (ret); ++ return NULL; ++ } ++ verified->file = io; ++ ret->data = verified; + return ret; + } + diff --git a/SOURCES/0176-Make-grub2-mkconfig-construct-titles-that-look-like-.patch b/SOURCES/0176-Make-grub2-mkconfig-construct-titles-that-look-like-.patch new file mode 100644 index 0000000..1c5edf2 --- /dev/null +++ b/SOURCES/0176-Make-grub2-mkconfig-construct-titles-that-look-like-.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 28 Apr 2015 11:15:03 -0400 +Subject: [PATCH] Make grub2-mkconfig construct titles that look like the ones + we want elsewhere. + +Resolves: rhbz#1215839 + +Signed-off-by: Peter Jones +--- + util/grub.d/10_linux.in | 34 +++++++++++++++++++++++++++------- + 1 file changed, 27 insertions(+), 7 deletions(-) + +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index e8088a18160..b3c460cb266 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -66,6 +66,32 @@ case x"$GRUB_FS" in + ;; + esac + ++mktitle () ++{ ++ local title_type ++ local version ++ local OS_NAME ++ local OS_VERS ++ ++ title_type=$1 && shift ++ version=$1 && shift ++ ++ OS_NAME="$(eval $(grep ^NAME= /etc/os-release) ; echo ${NAME})" ++ OS_VERS="$(eval $(grep ^VERSION= /etc/os-release) ; echo ${VERSION})" ++ ++ case $title_type in ++ recovery) ++ title=$(printf '%s (%s) %s (recovery mode)' \ ++ "${OS_NAME}" "${version}" "${OS_VERS}") ++ ;; ++ *) ++ title=$(printf '%s (%s) %s' \ ++ "${OS_NAME}" "${version}" "${OS_VERS}") ++ ;; ++ esac ++ echo -n ${title} ++} ++ + title_correction_code= + + linux_entry () +@@ -94,17 +120,11 @@ linux_entry () + boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")" + fi + if [ x$type != xsimple ] ; then +- case $type in +- recovery) +- title="$(gettext_printf "%s, with Linux %s (recovery mode)" "${os}" "${version}")" ;; +- *) +- title="$(gettext_printf "%s, with Linux %s" "${os}" "${version}")" ;; +- esac ++ title=$(mktitle "$type" "$version") + if [ x"$title" = x"$GRUB_ACTUAL_DEFAULT" ] || [ x"Previous Linux versions>$title" = x"$GRUB_ACTUAL_DEFAULT" ]; then + replacement_title="$(echo "Advanced options for ${OS}" | sed 's,>,>>,g')>$(echo "$title" | sed 's,>,>>,g')" + quoted="$(echo "$GRUB_ACTUAL_DEFAULT" | grub_quote)" + title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;" +- grub_warn "$(gettext_printf "Please don't use old title \`%s' for GRUB_DEFAULT, use \`%s' (for versions before 2.00) or \`%s' (for 2.00 or later)" "$GRUB_ACTUAL_DEFAULT" "$replacement_title" "gnulinux-advanced-$boot_device_id>gnulinux-$version-$type-$boot_device_id")" + fi + echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' {" | sed "s/^/$submenu_indentation/" + else diff --git a/SOURCES/0177-don-t-strip-fw_path-twice-for-EFI-network-boot.patch b/SOURCES/0177-don-t-strip-fw_path-twice-for-EFI-network-boot.patch new file mode 100644 index 0000000..622955e --- /dev/null +++ b/SOURCES/0177-don-t-strip-fw_path-twice-for-EFI-network-boot.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: RHEL Ninjas +Date: Mon, 13 Apr 2015 12:42:53 +1000 +Subject: [PATCH] don't strip fw_path twice for EFI network boot + +--- + grub-core/kern/efi/init.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c +index 942ab0256b9..c391df48236 100644 +--- a/grub-core/kern/efi/init.c ++++ b/grub-core/kern/efi/init.c +@@ -61,7 +61,12 @@ grub_machine_get_bootlocation (char **device, char **path) + *device = grub_efidisk_get_device_name (image->device_handle); + *path = grub_efi_get_filename (image->file_path); + if (!*device && grub_efi_net_config) +- grub_efi_net_config (image->device_handle, device, path); ++ { ++ grub_efi_net_config (image->device_handle, device, path); ++ /* grub_efi_net_config returns the directory path, not the boot filename, ++ so don't strip any further. */ ++ return; ++ } + + /* Get the directory. */ + p = grub_strrchr (*path, '/'); diff --git a/SOURCES/0178-Add-friendly-grub2-password-config-tool-985962.patch b/SOURCES/0178-Add-friendly-grub2-password-config-tool-985962.patch new file mode 100644 index 0000000..d53e093 --- /dev/null +++ b/SOURCES/0178-Add-friendly-grub2-password-config-tool-985962.patch @@ -0,0 +1,279 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robert Marshall +Date: Thu, 25 Jun 2015 11:13:11 -0400 +Subject: [PATCH] Add friendly grub2 password config tool (#985962) + +Provided a tool for users to reset the grub2 root user password +without having to alter the grub.cfg. The hashed password now +lives in a root-only-readable configuration file. + +Resolves: rhbz#985962 +--- + configure.ac | 1 + + Makefile.util.def | 13 +++++ + .gitignore | 12 ++--- + util/grub-mkconfig.in | 2 + + util/grub-setpassword.8 | 28 +++++++++++ + util/grub-setpassword.in | 123 +++++++++++++++++++++++++++++++++++++++++++++++ + util/grub.d/01_users.in | 11 +++++ + 7 files changed, 182 insertions(+), 8 deletions(-) + create mode 100644 util/grub-setpassword.8 + create mode 100755 util/grub-setpassword.in + create mode 100644 util/grub.d/01_users.in + +diff --git a/configure.ac b/configure.ac +index de17e65c4b7..273da6cb906 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -65,6 +65,7 @@ grub_TRANSFORM([grub-mkrelpath]) + grub_TRANSFORM([grub-mkrescue]) + grub_TRANSFORM([grub-probe]) + grub_TRANSFORM([grub-reboot]) ++grub_TRANSFORM([grub-setpassword]) + grub_TRANSFORM([grub-rpm-sort]) + grub_TRANSFORM([grub-script-check]) + grub_TRANSFORM([grub-set-default]) +diff --git a/Makefile.util.def b/Makefile.util.def +index 3ac75720466..e2821a2f3a5 100644 +--- a/Makefile.util.def ++++ b/Makefile.util.def +@@ -437,6 +437,12 @@ script = { + installdir = grubconf; + }; + ++script = { ++ name = '01_users'; ++ common = util/grub.d/01_users.in; ++ installdir = grubconf; ++}; ++ + script = { + name = '10_windows'; + common = util/grub.d/10_windows.in; +@@ -712,6 +718,13 @@ script = { + installdir = sbin; + }; + ++script = { ++ name = grub-setpassword; ++ common = util/grub-setpassword.in; ++ mansection = 8; ++ installdir = sbin; ++}; ++ + script = { + name = grub-mkconfig_lib; + common = util/grub-mkconfig_lib.in; +diff --git a/.gitignore b/.gitignore +index b6c45776a4d..e49f76b114a 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -1,11 +1,7 @@ +-00_header +-10_* +-20_linux_xen +-30_os-prober +-40_custom +-41_custom +-*.1 +-*.8 ++[[:digit:]][[:digit:]]_* ++!util/[[:digit:]][[:digit:]]_*.in ++*.[[:digit:]] ++!util/*.[[:digit:]] + aclocal.m4 + ahci_test + ascii.bitmaps +diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in +index bc26e7c109e..e029d0d5ea9 100644 +--- a/util/grub-mkconfig.in ++++ b/util/grub-mkconfig.in +@@ -260,6 +260,8 @@ for i in "${grub_mkconfig_dir}"/* ; do + *~) ;; + # emacsen autosave files. FIXME: support other editors + */\#*\#) ;; ++ # rpm config files of yore. ++ *.rpmsave|*.rpmnew|*.rpmorig) ;; + *) + if grub_file_is_not_garbage "$i" && test -x "$i" ; then + echo +diff --git a/util/grub-setpassword.8 b/util/grub-setpassword.8 +new file mode 100644 +index 00000000000..5973abef4ab +--- /dev/null ++++ b/util/grub-setpassword.8 +@@ -0,0 +1,28 @@ ++.TH GRUB-SETPASSWORD 3 "Thu Jun 25 2015" ++.SH NAME ++\fBgrub-setpassword\fR \(em Generate the user.cfg file containing the hashed grub bootloader password. ++ ++.SH SYNOPSIS ++\fBgrub-setpassword\fR [OPTION] ++ ++.SH DESCRIPTION ++\fBgrub-setpassword\fR outputs the user.cfg file which contains the hashed GRUB bootloader password. This utility only supports configurations where there is a single root user. ++ ++The file has the format: ++GRUB_2PASSWORD=<\fIhashed password\fR>. ++ ++.SH OPTIONS ++.TP ++-h, --help ++Display program usage and exit. ++.TP ++-v, --version ++Display the current version. ++.TP ++-o, --output[=\fIDIRECTORY PATH\fR] ++Choose the file path to which user.cfg will be written. ++ ++.SH SEE ALSO ++.BR "info grub" ++ ++.BR "info grub2-mkpasswd-pbkdf2" +diff --git a/util/grub-setpassword.in b/util/grub-setpassword.in +new file mode 100755 +index 00000000000..dd76f00fc0e +--- /dev/null ++++ b/util/grub-setpassword.in +@@ -0,0 +1,123 @@ ++#!/bin/sh -e ++ ++if [ -d /sys/firmware/efi/efivars/ ]; then ++ grubdir=`echo "/@bootdirname@/efi/EFI/redhat/" | sed 's,//*,/,g'` ++else ++ grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'` ++fi ++ ++PACKAGE_VERSION="@PACKAGE_VERSION@" ++PACKAGE_NAME="@PACKAGE_NAME@" ++self=`basename $0` ++bindir="@bindir@" ++grub_mkpasswd="${bindir}/@grub_mkpasswd_pbkdf2@" ++ ++# Usage: usage ++# Print the usage. ++usage () { ++ cat <&2 ++ exit 1 ++ fi ++ echo $1 ++} ++ ++# Ensure that it's the root user running this script ++if [ "${EUID}" -ne 0 ]; then ++ echo "The grub bootloader password may only be set by root." ++ usage ++ exit 2 ++fi ++ ++# Check the arguments. ++while test $# -gt 0 ++do ++ option=$1 ++ shift ++ ++ case "$option" in ++ -h | --help) ++ usage ++ exit 0 ;; ++ -v | --version) ++ echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" ++ exit 0 ;; ++ -o | --output) ++ OUTPUT_PATH=`argument $option "$@"`; shift ;; ++ --output=*) ++ OUTPUT_PATH=`echo "$option" | sed 's/--output=//'` ;; ++ -o=*) ++ OUTPUT_PATH=`echo "$option" | sed 's/-o=//'` ;; ++ esac ++done ++ ++# set user input or default path for user.cfg file ++if [ -z "${OUTPUT_PATH}" ]; then ++ OUTPUT_PATH="${grubdir}" ++fi ++ ++if [ ! -d "${OUTPUT_PATH}" ]; then ++ echo "${OUTPUT_PATH} does not exist." ++ usage ++ exit 2; ++fi ++ ++ttyopt=$(stty -g) ++fixtty() { ++ stty ${ttyopt} ++} ++ ++trap fixtty EXIT ++stty -echo ++ ++# prompt & confirm new grub2 root user password ++echo -n "Enter password: " ++read PASSWORD ++echo ++echo -n "Confirm password: " ++read PASSWORD_CONFIRM ++echo ++stty ${ttyopt} ++ ++getpass() { ++ local P0 ++ local P1 ++ P0="$1" && shift ++ P1="$1" && shift ++ ++ ( echo ${P0} ; echo ${P1} ) | \ ++ ${grub_mkpasswd} | \ ++ grep -v '[eE]nter password:' | \ ++ sed -e "s/PBKDF2 hash of your password is //" ++} ++ ++MYPASS="$(getpass "${PASSWORD}" "${PASSWORD_CONFIRM}")" ++if [ -z "${MYPASS}" ]; then ++ echo "${self}: error: empty password" 1>&2 ++ exit 1 ++fi ++ ++# on the ESP, these will fail to set the permissions, but it's okay because ++# the directory is protected. ++install -m 0600 /dev/null "${grubdir}/user.cfg" 2>/dev/null || : ++chmod 0600 "${grubdir}/user.cfg" 2>/dev/null || : ++echo "GRUB2_PASSWORD=${MYPASS}" > "${grubdir}/user.cfg" +diff --git a/util/grub.d/01_users.in b/util/grub.d/01_users.in +new file mode 100644 +index 00000000000..facd409e722 +--- /dev/null ++++ b/util/grub.d/01_users.in +@@ -0,0 +1,11 @@ ++#!/bin/sh -e ++cat << EOF ++if [ -f \${prefix}/user.cfg ]; then ++ source \${prefix}/user.cfg ++ if [ -n \${GRUB2_PASSWORD} ]; then ++ set superusers="root" ++ export superusers ++ password_pbkdf2 root \${GRUB2_PASSWORD} ++ fi ++fi ++EOF diff --git a/SOURCES/0179-Try-to-make-sure-configure.ac-and-grub-rpm-sort-play.patch b/SOURCES/0179-Try-to-make-sure-configure.ac-and-grub-rpm-sort-play.patch new file mode 100644 index 0000000..eba3892 --- /dev/null +++ b/SOURCES/0179-Try-to-make-sure-configure.ac-and-grub-rpm-sort-play.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 3 Aug 2015 11:46:42 -0400 +Subject: [PATCH] Try to make sure configure.ac and grub-rpm-sort play nice. + +Apparently the test for whether to use grub-rpm-sort and also the +renaming of it to grub2-rpm-sort on the runtime side weren't right. + +Related: rhbz#1124074 + +Signed-off-by: Peter Jones +--- + configure.ac | 2 +- + util/grub-mkconfig_lib.in | 9 ++++++--- + 2 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 273da6cb906..04c052dc610 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1549,7 +1549,7 @@ AC_SUBST([LIBDEVMAPPER]) + AC_ARG_ENABLE([rpm-sort], + [AS_HELP_STRING([--enable-rpm-sort], + [enable native rpm sorting of kernels in grub (default=guessed)])]) +-if test x"$enable_rpm-sort" = xno ; then ++if test x"$enable_rpm_sort" = xno ; then + rpm_sort_excuse="explicitly disabled" + fi + +diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in +index e85b60c322a..c67a319916a 100644 +--- a/util/grub-mkconfig_lib.in ++++ b/util/grub-mkconfig_lib.in +@@ -33,6 +33,9 @@ fi + if test "x$grub_mkrelpath" = x; then + grub_mkrelpath="${bindir}/@grub_mkrelpath@" + fi ++if test "x$grub_rpm_sort" = x; then ++ grub_rpm_sort="${sbindir}/@grub_rpm_sort@" ++fi + + if which gettext >/dev/null 2>/dev/null; then + : +@@ -213,10 +216,10 @@ version_sort () + esac + } + +-if [ "x$RPMLIB" = x ]; then ++if [ "x$grub_rpm_sort" != x -a -x "$grub_rpm_sort" ]; then ++ kernel_sort="$grub_rpm_sort" ++else + kernel_sort=version_sort +-else +- kernel_sort="${sbindir}/grub-rpm-sort" + fi + + version_test_numeric () diff --git a/SOURCES/0180-ppc64le-sync-mkconfig-to-disk-1212114.patch b/SOURCES/0180-ppc64le-sync-mkconfig-to-disk-1212114.patch new file mode 100644 index 0000000..27a337b --- /dev/null +++ b/SOURCES/0180-ppc64le-sync-mkconfig-to-disk-1212114.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Don Zickus +Date: Wed, 22 Jul 2015 13:59:55 -0400 +Subject: [PATCH] ppc64le sync mkconfig to disk (#1212114) + +If creating a new grub2 entry using grub2-mkconfig, the entry is not +immediately sync'd to disk. If a crash happens before the writeback, +the subsequent reboot fails because the grub2.cfg is corrupted. + +Address this by forcing all the changes (mainly the fs meta data) to disk +before finishing the grub2 conf changes. + +Tested by 'grub2-mkconfig -o /etc/grub22.cfg; echo c > /proc/sysrq-trigger'. + +Before, the machine would panic and on reboot be stuck without a grub.cfg +to read. After, works as expected. + +Resolves: rhbz#1212114 +--- + util/grub-mkconfig.in | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in +index e029d0d5ea9..cf315e241f6 100644 +--- a/util/grub-mkconfig.in ++++ b/util/grub-mkconfig.in +@@ -290,3 +290,12 @@ fi + + gettext "done" >&2 + echo >&2 ++ ++# make sure changes make it to the disk. ++# if /boot is a mountpoint, force the meta data on disk ++# to by-pass writeback delay. ++# PPC64LE-only to deal with Petitboot issues ++ARCH=$(uname -m) ++if [ "${ARCH}" = "ppc64le" ]; then ++ sync && mountpoint -q /boot &&fsfreeze -f /boot && fsfreeze -u /boot ++fi diff --git a/SOURCES/0181-tcp-ack-when-we-get-an-OOO-lost-packet.patch b/SOURCES/0181-tcp-ack-when-we-get-an-OOO-lost-packet.patch new file mode 100644 index 0000000..071bcbe --- /dev/null +++ b/SOURCES/0181-tcp-ack-when-we-get-an-OOO-lost-packet.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Wed, 12 Aug 2015 08:16:22 -0700 +Subject: [PATCH] tcp: ack when we get an OOO/lost packet + +While adding tcp window scaling support I was finding that I'd get some packet +loss or reordering when transferring from large distances and grub would just +timeout. This is because we weren't ack'ing when we got our OOO packet, so the +sender didn't know it needed to retransmit anything, so eventually it would fill +the window and stop transmitting, and we'd time out. Fix this by ACK'ing when +we don't find our next sequence numbered packet. With this fix I no longer time +out. Thanks, + +Signed-off-by: Josef Bacik +--- + grub-core/net/tcp.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c +index 2077f5519b2..fa29a2afc6c 100644 +--- a/grub-core/net/tcp.c ++++ b/grub-core/net/tcp.c +@@ -882,7 +882,10 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb, + grub_priority_queue_pop (sock->pq); + } + if (grub_be_to_cpu32 (tcph->seqnr) != sock->their_cur_seq) +- return GRUB_ERR_NONE; ++ { ++ ack (sock); ++ return GRUB_ERR_NONE; ++ } + while (1) + { + nb_top_p = grub_priority_queue_top (sock->pq); diff --git a/SOURCES/0182-tcp-add-window-scaling-support.patch b/SOURCES/0182-tcp-add-window-scaling-support.patch new file mode 100644 index 0000000..4455fce --- /dev/null +++ b/SOURCES/0182-tcp-add-window-scaling-support.patch @@ -0,0 +1,87 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Wed, 12 Aug 2015 08:57:55 -0700 +Subject: [PATCH] tcp: add window scaling support + +Sometimes we have to provision boxes across regions, such as California to +Sweden. The http server has a 10 minute timeout, so if we can't get our 250mb +image transferred fast enough our provisioning fails, which is not ideal. So +add tcp window scaling on open connections and set the window size to 1mb. With +this change we're able to get higher sustained transfers between regions and can +transfer our image in well below 10 minutes. Without this patch we'd time out +every time halfway through the transfer. Thanks, + +Signed-off-by: Josef Bacik +--- + grub-core/net/tcp.c | 42 +++++++++++++++++++++++++++++------------- + 1 file changed, 29 insertions(+), 13 deletions(-) + +diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c +index fa29a2afc6c..c22ef033d6e 100644 +--- a/grub-core/net/tcp.c ++++ b/grub-core/net/tcp.c +@@ -106,6 +106,18 @@ struct tcphdr + grub_uint16_t urgent; + } GRUB_PACKED; + ++struct tcp_scale_opt { ++ grub_uint8_t kind; ++ grub_uint8_t length; ++ grub_uint8_t scale; ++} GRUB_PACKED; ++ ++struct tcp_synhdr { ++ struct tcphdr tcphdr; ++ struct tcp_scale_opt scale_opt; ++ grub_uint8_t padding; ++}; ++ + struct tcp_pseudohdr + { + grub_uint32_t src; +@@ -555,7 +567,7 @@ grub_net_tcp_open (char *server, + grub_net_tcp_socket_t socket; + static grub_uint16_t in_port = 21550; + struct grub_net_buff *nb; +- struct tcphdr *tcph; ++ struct tcp_synhdr *tcph; + int i; + grub_uint8_t *nbd; + grub_net_link_level_address_t ll_target_addr; +@@ -617,20 +629,24 @@ grub_net_tcp_open (char *server, + } + + tcph = (void *) nb->data; ++ grub_memset(tcph, 0, sizeof (*tcph)); + socket->my_start_seq = grub_get_time_ms (); + socket->my_cur_seq = socket->my_start_seq + 1; +- socket->my_window = 8192; +- tcph->seqnr = grub_cpu_to_be32 (socket->my_start_seq); +- tcph->ack = grub_cpu_to_be32_compile_time (0); +- tcph->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_SYN); +- tcph->window = grub_cpu_to_be16 (socket->my_window); +- tcph->urgent = 0; +- tcph->src = grub_cpu_to_be16 (socket->in_port); +- tcph->dst = grub_cpu_to_be16 (socket->out_port); +- tcph->checksum = 0; +- tcph->checksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_TCP, +- &socket->inf->address, +- &socket->out_nla); ++ socket->my_window = 32768; ++ tcph->tcphdr.seqnr = grub_cpu_to_be32 (socket->my_start_seq); ++ tcph->tcphdr.ack = grub_cpu_to_be32_compile_time (0); ++ tcph->tcphdr.flags = grub_cpu_to_be16_compile_time ((6 << 12) | TCP_SYN); ++ tcph->tcphdr.window = grub_cpu_to_be16 (socket->my_window); ++ tcph->tcphdr.urgent = 0; ++ tcph->tcphdr.src = grub_cpu_to_be16 (socket->in_port); ++ tcph->tcphdr.dst = grub_cpu_to_be16 (socket->out_port); ++ tcph->tcphdr.checksum = 0; ++ tcph->scale_opt.kind = 3; ++ tcph->scale_opt.length = 3; ++ tcph->scale_opt.scale = 5; ++ tcph->tcphdr.checksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_TCP, ++ &socket->inf->address, ++ &socket->out_nla); + + tcp_socket_register (socket); + diff --git a/SOURCES/0183-efinet-retransmit-if-our-device-is-busy.patch b/SOURCES/0183-efinet-retransmit-if-our-device-is-busy.patch new file mode 100644 index 0000000..f932d7d --- /dev/null +++ b/SOURCES/0183-efinet-retransmit-if-our-device-is-busy.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Mon, 31 Aug 2015 13:34:35 -0400 +Subject: [PATCH] efinet: retransmit if our device is busy + +When I fixed the txbuf handling I ripped out the retransmission code since it +was flooding our network when we had the buggy behavior. Turns out this was too +heavy handed as we can still have transient tx timeouts. So instead make sure +we retry our transmission once per timeout. This way we can deal with transient +transmission problems without flooding the box. This fixes an issue we were +seeing in production. Thanks, + +Signed-off-by: Josef Bacik +--- + grub-core/net/drivers/efi/efinet.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index ea0e0ca360e..c3a128cd1dc 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -38,6 +38,7 @@ send_card_buffer (struct grub_net_card *dev, + grub_efi_simple_network_t *net = dev->efi_net; + grub_uint64_t limit_time = grub_get_time_ms () + 4000; + void *txbuf; ++ int retry = 0; + + if (dev->txbusy) + while (1) +@@ -60,6 +61,15 @@ send_card_buffer (struct grub_net_card *dev, + dev->txbusy = 0; + break; + } ++ if (!retry) ++ { ++ st = efi_call_7 (net->transmit, net, 0, dev->last_pkt_size, ++ dev->txbuf, NULL, NULL, NULL); ++ if (st != GRUB_EFI_SUCCESS) ++ return grub_error (GRUB_ERR_IO, ++ N_("couldn't send network packet")); ++ retry = 1; ++ } + if (limit_time < grub_get_time_ms ()) + return grub_error (GRUB_ERR_TIMEOUT, + N_("couldn't send network packet")); diff --git a/SOURCES/0184-efinet-add-filter-for-the-first-exclusive-reopen-of-.patch b/SOURCES/0184-efinet-add-filter-for-the-first-exclusive-reopen-of-.patch new file mode 100644 index 0000000..8078da6 --- /dev/null +++ b/SOURCES/0184-efinet-add-filter-for-the-first-exclusive-reopen-of-.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: RHEL Ninjas +Date: Fri, 25 Sep 2015 16:24:23 +0900 +Subject: [PATCH] efinet: add filter for the first exclusive reopen of SNP + +--- + grub-core/net/drivers/efi/efinet.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index c3a128cd1dc..d8099a59855 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -407,6 +407,30 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + if (net->mode->state == GRUB_EFI_NETWORK_STARTED + && efi_call_3 (net->initialize, net, 0, 0) != GRUB_EFI_SUCCESS) + continue; ++ ++ /* Enable hardware receive filters if driver declares support for it. ++ We need unicast and broadcast and additionaly all nodes and ++ solicited multicast for IPv6. Solicited multicast is per-IPv6 ++ address and we currently do not have API to do it so simply ++ try to enable receive of all multicast packets or evertyhing in ++ the worst case (i386 PXE driver always enables promiscuous too). ++ ++ This does trust firmware to do what it claims to do. ++ */ ++ if (net->mode->receive_filter_mask) ++ { ++ grub_uint32_t filters = GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | ++ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST | ++ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; ++ ++ filters &= net->mode->receive_filter_mask; ++ if (!(filters & GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST)) ++ filters |= (net->mode->receive_filter_mask & ++ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS); ++ ++ efi_call_6 (net->receive_filters, net, filters, 0, 0, 0, NULL); ++ } ++ + card->efi_net = net; + } + return; diff --git a/SOURCES/0185-Fix-security-issue-when-reading-username-and-passwor.patch b/SOURCES/0185-Fix-security-issue-when-reading-username-and-passwor.patch new file mode 100644 index 0000000..d000899 --- /dev/null +++ b/SOURCES/0185-Fix-security-issue-when-reading-username-and-passwor.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hector Marco-Gisbert +Date: Fri, 13 Nov 2015 16:21:09 +0100 +Subject: [PATCH] Fix security issue when reading username and password + + This patch fixes two integer underflows at: + * grub-core/lib/crypto.c + * grub-core/normal/auth.c + +Resolves: CVE-2015-8370 + +Signed-off-by: Hector Marco-Gisbert +Signed-off-by: Ismael Ripoll-Ripoll +--- + grub-core/lib/crypto.c | 2 +- + grub-core/normal/auth.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c +index 8e8426c4ab4..a23519cb3bd 100644 +--- a/grub-core/lib/crypto.c ++++ b/grub-core/lib/crypto.c +@@ -456,7 +456,7 @@ grub_password_get (char buf[], unsigned buf_size) + break; + } + +- if (key == '\b') ++ if (key == '\b' && cur_len) + { + cur_len--; + continue; +diff --git a/grub-core/normal/auth.c b/grub-core/normal/auth.c +index c6bd96e28ec..5782ec5a940 100644 +--- a/grub-core/normal/auth.c ++++ b/grub-core/normal/auth.c +@@ -172,7 +172,7 @@ grub_username_get (char buf[], unsigned buf_size) + break; + } + +- if (key == '\b') ++ if (key == '\b' && cur_len) + { + cur_len--; + grub_printf ("\b"); diff --git a/SOURCES/0186-01_users-Handle-GRUB_PASSWORD-better.patch b/SOURCES/0186-01_users-Handle-GRUB_PASSWORD-better.patch new file mode 100644 index 0000000..88ef564 --- /dev/null +++ b/SOURCES/0186-01_users-Handle-GRUB_PASSWORD-better.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 4 Dec 2015 09:28:38 -0500 +Subject: [PATCH] 01_users: Handle GRUB_PASSWORD better. + +Only handle GRUB_PASSWORD not GRUB2_PASSWORD (as that's more likely to +be acceptable upstream). + +Related: rhbz#1284370 + +Signed-off-by: Peter Jones +--- + util/grub-setpassword.8 | 2 +- + util/grub.d/01_users.in | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/util/grub-setpassword.8 b/util/grub-setpassword.8 +index 5973abef4ab..49200a848b7 100644 +--- a/util/grub-setpassword.8 ++++ b/util/grub-setpassword.8 +@@ -9,7 +9,7 @@ + \fBgrub-setpassword\fR outputs the user.cfg file which contains the hashed GRUB bootloader password. This utility only supports configurations where there is a single root user. + + The file has the format: +-GRUB_2PASSWORD=<\fIhashed password\fR>. ++GRUB2_PASSWORD=<\fIhashed password\fR>. + + .SH OPTIONS + .TP +diff --git a/util/grub.d/01_users.in b/util/grub.d/01_users.in +index facd409e722..db2f44bfb78 100644 +--- a/util/grub.d/01_users.in ++++ b/util/grub.d/01_users.in +@@ -2,7 +2,7 @@ + cat << EOF + if [ -f \${prefix}/user.cfg ]; then + source \${prefix}/user.cfg +- if [ -n \${GRUB2_PASSWORD} ]; then ++ if [ -n "\${GRUB2_PASSWORD}" ]; then + set superusers="root" + export superusers + password_pbkdf2 root \${GRUB2_PASSWORD} diff --git a/SOURCES/0187-Failed-config-now-returns-exit-code-1252311.patch b/SOURCES/0187-Failed-config-now-returns-exit-code-1252311.patch new file mode 100644 index 0000000..f82c897 --- /dev/null +++ b/SOURCES/0187-Failed-config-now-returns-exit-code-1252311.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robert Marshall +Date: Fri, 29 Jan 2016 14:49:24 -0500 +Subject: [PATCH] Failed config now returns exit code (#1252311) + +Grub would notify the user if the new config was invalid, however, it +did not exit properly with exit code 1. Added the proper exit code. + +Resolves: rhbz#1252311 +--- + util/grub-mkconfig.in | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in +index cf315e241f6..7db89499949 100644 +--- a/util/grub-mkconfig.in ++++ b/util/grub-mkconfig.in +@@ -281,6 +281,7 @@ Ensure that there are no errors in /etc/default/grub + and /etc/grub.d/* files or please file a bug report with + %s file attached." "${grub_cfg}.new" >&2 + echo >&2 ++ exit 1 + else + # none of the children aborted with error, install the new grub.cfg + cat ${grub_cfg}.new > ${grub_cfg} diff --git a/SOURCES/0188-Warn-if-grub-password-will-not-be-read-1290803.patch b/SOURCES/0188-Warn-if-grub-password-will-not-be-read-1290803.patch new file mode 100644 index 0000000..4baf91a --- /dev/null +++ b/SOURCES/0188-Warn-if-grub-password-will-not-be-read-1290803.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robert Marshall +Date: Mon, 22 Feb 2016 15:30:05 -0500 +Subject: [PATCH] Warn if grub password will not be read (#1290803) + +It is possible for a system to have never run grub-mkconfig and add the +section that reads the user.cfg file which contains a user set GRUB +password. Users in that scenario will now be warned that grub-mkconfig +must be run prior to their newly set password taking effect. + +Resolves: rhbz#1290803 +--- + util/grub-setpassword.in | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/util/grub-setpassword.in b/util/grub-setpassword.in +index dd76f00fc0e..fb9d3a3b6f9 100755 +--- a/util/grub-setpassword.in ++++ b/util/grub-setpassword.in +@@ -121,3 +121,8 @@ fi + install -m 0600 /dev/null "${grubdir}/user.cfg" 2>/dev/null || : + chmod 0600 "${grubdir}/user.cfg" 2>/dev/null || : + echo "GRUB2_PASSWORD=${MYPASS}" > "${grubdir}/user.cfg" ++ ++if ! grep -q "^### BEGIN /etc/grub.d/01_users ###$" "${grubdir}/grub.cfg"; then ++ echo "WARNING: The current configuration lacks password support!" ++ echo "Update your configuration with @grub_mkconfig@ to support this feature." ++fi diff --git a/SOURCES/0189-Clean-up-grub-setpassword-documentation-1290799.patch b/SOURCES/0189-Clean-up-grub-setpassword-documentation-1290799.patch new file mode 100644 index 0000000..b5ad6ec --- /dev/null +++ b/SOURCES/0189-Clean-up-grub-setpassword-documentation-1290799.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robert Marshall +Date: Tue, 26 Jan 2016 10:28:35 -0500 +Subject: [PATCH] Clean up grub-setpassword documentation (#1290799) + +The output for --help had some errors. Corrected those and polished the +text to be a little easier to follow. Carried verbage over to man page +to maintain internal consistency. + +Resolves: rhbz#1290799 +--- + util/grub-setpassword.8 | 2 +- + util/grub-setpassword.in | 15 +++++++-------- + 2 files changed, 8 insertions(+), 9 deletions(-) + +diff --git a/util/grub-setpassword.8 b/util/grub-setpassword.8 +index 49200a848b7..dc91dd6697b 100644 +--- a/util/grub-setpassword.8 ++++ b/util/grub-setpassword.8 +@@ -19,7 +19,7 @@ Display program usage and exit. + -v, --version + Display the current version. + .TP +--o, --output[=\fIDIRECTORY PATH\fR] ++-o, --output=<\fIDIRECTORY\fR> + Choose the file path to which user.cfg will be written. + + .SH SEE ALSO +diff --git a/util/grub-setpassword.in b/util/grub-setpassword.in +index fb9d3a3b6f9..c8c0fa4199d 100755 +--- a/util/grub-setpassword.in ++++ b/util/grub-setpassword.in +@@ -16,15 +16,14 @@ grub_mkpasswd="${bindir}/@grub_mkpasswd_pbkdf2@" + # Print the usage. + usage () { + cat < put user.cfg in a user-selected directory + + Report bugs at https://bugzilla.redhat.com. + EOF diff --git a/SOURCES/0190-Fix-locale-issue-in-grub-setpassword-1294243.patch b/SOURCES/0190-Fix-locale-issue-in-grub-setpassword-1294243.patch new file mode 100644 index 0000000..4ab663d --- /dev/null +++ b/SOURCES/0190-Fix-locale-issue-in-grub-setpassword-1294243.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robert Marshall +Date: Fri, 29 Jan 2016 16:56:11 -0500 +Subject: [PATCH] Fix locale issue in grub-setpassword (#1294243) + +A shell substitution was expecting non-translated output to grab the +hashed password and put it in the user.cfg file. Modified code to force +the generic C locale when this particular piece of code is run. + +Resolves: rhbz#1294243 +--- + util/grub-setpassword.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/util/grub-setpassword.in b/util/grub-setpassword.in +index c8c0fa4199d..d7924af5192 100755 +--- a/util/grub-setpassword.in ++++ b/util/grub-setpassword.in +@@ -104,7 +104,7 @@ getpass() { + P1="$1" && shift + + ( echo ${P0} ; echo ${P1} ) | \ +- ${grub_mkpasswd} | \ ++ LC_ALL=C ${grub_mkpasswd} | \ + grep -v '[eE]nter password:' | \ + sed -e "s/PBKDF2 hash of your password is //" + } diff --git a/SOURCES/0191-efi-really-mark-memory-of-unknown-type-as-reserved.patch b/SOURCES/0191-efi-really-mark-memory-of-unknown-type-as-reserved.patch new file mode 100644 index 0000000..70dfa71 --- /dev/null +++ b/SOURCES/0191-efi-really-mark-memory-of-unknown-type-as-reserved.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Thu, 26 Nov 2015 19:50:42 +0300 +Subject: [PATCH] efi: really mark memory of unknown type as reserved + +9be4c45dbe3c877d1f4856e99ee15133c6cd2261 added switch case between +fall through cases, causing all memory regions of unknown type to be +marked as available. + +Move default case into its own block and add explicit FALLTHROUGH +annotation. + +Reported by Elliott, Robert (Persistent Memory) + +(cherry picked from commit 3d2c8048da7db334fd6d57b27304ac765fd4cd67) + +Resolves: rhbz#1288608 +--- + grub-core/mmap/efi/mmap.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/grub-core/mmap/efi/mmap.c b/grub-core/mmap/efi/mmap.c +index a77efe81d0c..900a4d6598c 100644 +--- a/grub-core/mmap/efi/mmap.c ++++ b/grub-core/mmap/efi/mmap.c +@@ -73,6 +73,7 @@ grub_efi_mmap_iterate (grub_memory_hook_t hook, void *hook_data, + GRUB_MEMORY_AVAILABLE, hook_data); + break; + } ++ /* FALLTHROUGH */ + case GRUB_EFI_RUNTIME_SERVICES_CODE: + hook (desc->physical_start, desc->num_pages * 4096, + GRUB_MEMORY_CODE, hook_data); +@@ -83,10 +84,6 @@ grub_efi_mmap_iterate (grub_memory_hook_t hook, void *hook_data, + GRUB_MEMORY_BADRAM, hook_data); + break; + +- default: +- grub_printf ("Unknown memory type %d, considering reserved\n", +- desc->type); +- + case GRUB_EFI_BOOT_SERVICES_DATA: + if (!avoid_efi_boot_services) + { +@@ -94,6 +91,7 @@ grub_efi_mmap_iterate (grub_memory_hook_t hook, void *hook_data, + GRUB_MEMORY_AVAILABLE, hook_data); + break; + } ++ /* FALLTHROUGH */ + case GRUB_EFI_RESERVED_MEMORY_TYPE: + case GRUB_EFI_RUNTIME_SERVICES_DATA: + case GRUB_EFI_MEMORY_MAPPED_IO: +@@ -119,6 +117,13 @@ grub_efi_mmap_iterate (grub_memory_hook_t hook, void *hook_data, + hook (desc->physical_start, desc->num_pages * 4096, + GRUB_MEMORY_NVS, hook_data); + break; ++ ++ default: ++ grub_printf ("Unknown memory type %d, considering reserved\n", ++ desc->type); ++ hook (desc->physical_start, desc->num_pages * 4096, ++ GRUB_MEMORY_RESERVED, hook_data); ++ break; + } + } + diff --git a/SOURCES/0192-Translate-UEFI-persistent-memory-type.patch b/SOURCES/0192-Translate-UEFI-persistent-memory-type.patch new file mode 100644 index 0000000..20d2adc --- /dev/null +++ b/SOURCES/0192-Translate-UEFI-persistent-memory-type.patch @@ -0,0 +1,100 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robert Elliott +Date: Thu, 3 Dec 2015 11:38:36 -0600 +Subject: [PATCH] Translate UEFI persistent memory type +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Define +* GRUB_EFI_PERSISTENT_MEMORY (UEFI memory map type 14) per UEFI 2.5 +* GRUB_MEMORY_PERSISTENT (E820 type 7) per ACPI 3.0 +* GRUB_MEMORY_PERSISTENT_LEGACY (E820 unofficial type 12) per ACPI 3.0 + +and translate GRUB_EFI_PERSISTENT_MEMORY to GRUB_MEMORY_PERSISTENT in +grub_efi_mmap_iterate(). + +Includes +* adding the E820 names to lsmmap +* handling the E820 types in make_efi_memtype() + +Suggested-by: Vladimir 'φ-coder/phcoder' Serbinenko +Suggested-by: Andrei Borzenkov +(cherry picked from commit 76ce1de740f202985ffd7b2e980cf34c75a2dac3) + +Resolves: rhbz#1288608 +--- + grub-core/commands/lsmmap.c | 2 ++ + grub-core/mmap/efi/mmap.c | 12 ++++++++++++ + include/grub/efi/api.h | 1 + + include/grub/memory.h | 2 ++ + 4 files changed, 17 insertions(+) + +diff --git a/grub-core/commands/lsmmap.c b/grub-core/commands/lsmmap.c +index 4b504fd28f8..816ee47d1ed 100644 +--- a/grub-core/commands/lsmmap.c ++++ b/grub-core/commands/lsmmap.c +@@ -37,6 +37,8 @@ static const char *names[] = + is required to save accross hibernations. */ + [GRUB_MEMORY_NVS] = N_("ACPI non-volatile storage RAM"), + [GRUB_MEMORY_BADRAM] = N_("faulty RAM (BadRAM)"), ++ [GRUB_MEMORY_PERSISTENT] = N_("persistent RAM"), ++ [GRUB_MEMORY_PERSISTENT_LEGACY] = N_("persistent RAM (legacy)"), + [GRUB_MEMORY_COREBOOT_TABLES] = N_("RAM holding coreboot tables"), + [GRUB_MEMORY_CODE] = N_("RAM holding firmware code") + }; +diff --git a/grub-core/mmap/efi/mmap.c b/grub-core/mmap/efi/mmap.c +index 900a4d6598c..bd495a18481 100644 +--- a/grub-core/mmap/efi/mmap.c ++++ b/grub-core/mmap/efi/mmap.c +@@ -118,6 +118,11 @@ grub_efi_mmap_iterate (grub_memory_hook_t hook, void *hook_data, + GRUB_MEMORY_NVS, hook_data); + break; + ++ case GRUB_EFI_PERSISTENT_MEMORY: ++ hook (desc->physical_start, desc->num_pages * 4096, ++ GRUB_MEMORY_PERSISTENT, hook_data); ++ break; ++ + default: + grub_printf ("Unknown memory type %d, considering reserved\n", + desc->type); +@@ -147,6 +152,13 @@ make_efi_memtype (int type) + /* No way to remove a chunk of memory from EFI mmap. + So mark it as unusable. */ + case GRUB_MEMORY_HOLE: ++ /* ++ * AllocatePages() does not support GRUB_EFI_PERSISTENT_MEMORY, ++ * so no translation for GRUB_MEMORY_PERSISTENT or ++ * GRUB_MEMORY_PERSISTENT_LEGACY. ++ */ ++ case GRUB_MEMORY_PERSISTENT: ++ case GRUB_MEMORY_PERSISTENT_LEGACY: + case GRUB_MEMORY_RESERVED: + return GRUB_EFI_UNUSABLE_MEMORY; + +diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h +index 029ee92f5d0..551d93e50a3 100644 +--- a/include/grub/efi/api.h ++++ b/include/grub/efi/api.h +@@ -431,6 +431,7 @@ enum grub_efi_memory_type + GRUB_EFI_MEMORY_MAPPED_IO, + GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE, + GRUB_EFI_PAL_CODE, ++ GRUB_EFI_PERSISTENT_MEMORY, + GRUB_EFI_MAX_MEMORY_TYPE + }; + typedef enum grub_efi_memory_type grub_efi_memory_type_t; +diff --git a/include/grub/memory.h b/include/grub/memory.h +index 083cfb6802e..6da114a1bdc 100644 +--- a/include/grub/memory.h ++++ b/include/grub/memory.h +@@ -30,6 +30,8 @@ typedef enum grub_memory_type + GRUB_MEMORY_ACPI = 3, + GRUB_MEMORY_NVS = 4, + GRUB_MEMORY_BADRAM = 5, ++ GRUB_MEMORY_PERSISTENT = 7, ++ GRUB_MEMORY_PERSISTENT_LEGACY = 12, + GRUB_MEMORY_COREBOOT_TABLES = 16, + GRUB_MEMORY_CODE = 20, + /* This one is special: it's used internally but is never reported diff --git a/SOURCES/0193-lsefimmap-support-persistent-memory-and-other-UEFI-2.patch b/SOURCES/0193-lsefimmap-support-persistent-memory-and-other-UEFI-2.patch new file mode 100644 index 0000000..0d4791d --- /dev/null +++ b/SOURCES/0193-lsefimmap-support-persistent-memory-and-other-UEFI-2.patch @@ -0,0 +1,181 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robert Elliott +Date: Thu, 17 Dec 2015 10:53:32 -0600 +Subject: [PATCH] lsefimmap: support persistent memory and other UEFI 2.5 + features + +This should accompany + 76ce1de740 Translate UEFI persistent memory type + +1. Add a string for the EfiPersistentMemory type 14 that was +added in UEFI 2.5. + +2. Decode the memory attributes that were added in UEFI 2.5: +* NV (non-volatile) +* MORE_RELIABLE (higher reliable, e.g., mirrored memory in a system + with partial memory mirroring) +* RO (read-only) + +3. Use proper IEC binary units (KiB, MiB, etc.) for power-of-two +values rather than misusing SI power-of-ten units (KB, MB, etc.) + +4. The lsmmap command only decodes memory ranges sizes up to GiB scale +units. Persistent memory ranges will reach into the TiB scale. +Since 64-bit size field supports TiB, PiB, and EiB, decode all of +them for completeness. + +5. In the lsefimmap command, rewrite the print statements to +* avoid rounding +* avoid a big nested if/else tree. + +For example: In the sixth entry below, the value of 309MB implies +316416KB but is really reporting 316436KB. + +Widen the size column to 6 digits to accommodate typical cases. +The worst case value would require 14 digits; if that happens, +let the columns get out of sync. + +Old format: +Type Physical start - end #Pages Size Attributes +conv-mem 0000000000000000-0000000000092fff 00000093 588KB UC WC WT WB +reserved 0000000000093000-0000000000093fff 00000001 4KB UC WC WT WB +conv-mem 0000000000094000-000000000009ffff 0000000c 48KB UC WC WT WB +conv-mem 0000000000100000-000000000fffffff 0000ff00 255MB UC WC WT WB +BS-code 0000000010000000-0000000010048fff 00000049 292KB UC WC WT WB +conv-mem 0000000010049000-000000002354dfff 00013505 309MB UC WC WT WB +ldr-data 000000002354e000-000000003ecfffff 0001b7b2 439MB UC WC WT WB +BS-data 000000003ed00000-000000003ed7ffff 00000080 512KB UC WC WT WB +conv-mem 000000003ed80000-000000006af5ffff 0002c1e0 705MB UC WC WT WB +reserved 000000006af60000-000000006b55ffff 00000600 6MB UC WC WT WB +BS-data 000000006b560000-000000006b560fff 00000001 4KB UC WC WT WB +RT-data 000000006b561000-000000006b5e1fff 00000081 516KB RT UC WC WT WB +BS-data 000000006b5e2000-000000006ecfafff 00003719 55MB UC WC WT WB +BS-code 000000006ecfb000-000000006ecfbfff 00000001 4KB UC WC WT WB +conv-mem 000000006ecfc000-00000000711fafff 000024ff 36MB UC WC WT WB +BS-data 00000000711fb000-000000007128dfff 00000093 588KB UC WC WT WB +Unk 0d 0000000880000000-0000000e7fffffff 00600000 24GB UC WC WT WB NV +reserved 0000001680000000-0000001c7fffffff 00600000 24GB UC WC WT WB NV + +New format: +Type Physical start - end #Pages Size Attributes +conv-mem 0000000000000000-0000000000092fff 00000093 588KiB UC WC WT WB +reserved 0000000000093000-0000000000093fff 00000001 4KiB UC WC WT WB +conv-mem 0000000000094000-000000000009ffff 0000000c 48KiB UC WC WT WB +conv-mem 0000000000100000-000000000fffffff 0000ff00 255MiB UC WC WT WB +BS-code 0000000010000000-0000000010048fff 00000049 292KiB UC WC WT WB +conv-mem 0000000010049000-000000002354dfff 00013505 316436KiB UC WC WT WB +ldr-data 000000002354e000-000000003ecfffff 0001b7b2 450248KiB UC WC WT WB +BS-data 000000003ed00000-000000003ed7ffff 00000080 512KiB UC WC WT WB +conv-mem 000000003ed80000-000000006af5ffff 0002c1e0 722816KiB UC WC WT WB +reserved 000000006af60000-000000006b55ffff 00000600 6MiB UC WC WT WB +BS-data 000000006b560000-000000006b560fff 00000001 4KiB UC WC WT WB +RT-data 000000006b561000-000000006b5e1fff 00000081 516KiB RT UC WC WT WB +BS-data 000000006b5e2000-000000006ecfafff 00003719 56420KiB UC WC WT WB +BS-code 000000006ecfb000-000000006ecfbfff 00000001 4KiB UC WC WT WB +conv-mem 000000006ecfc000-0000000071222fff 00002527 38044KiB UC WC WT WB +BS-data 0000000071223000-00000000712ddfff 000000bb 748KiB UC WC WT WB +persist 0000000880000000-0000000e7fffffff 00600000 24GiB UC WC WT WB NV +reserved 0000001680000000-0000001c7fffffff 00600000 24GiB UC WC WT WB NV + +(cherry picked from commit c79c59f1295df8ea660f8a858f9532d76a5f67b7) + +Resolves: rhbz#1288608 +--- + grub-core/commands/efi/lsefimmap.c | 47 +++++++++++++++++++++++++------------- + include/grub/efi/api.h | 3 +++ + 2 files changed, 34 insertions(+), 16 deletions(-) + +diff --git a/grub-core/commands/efi/lsefimmap.c b/grub-core/commands/efi/lsefimmap.c +index 215b45bff80..c85ff7f366d 100644 +--- a/grub-core/commands/efi/lsefimmap.c ++++ b/grub-core/commands/efi/lsefimmap.c +@@ -51,7 +51,7 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)), + + grub_printf + ("Type Physical start - end #Pages " +- " Size Attributes\n"); ++ " Size Attributes\n"); + memory_map_end = ADD_MEMORY_DESCRIPTOR (memory_map, map_size); + for (desc = memory_map; + desc < memory_map_end; +@@ -74,7 +74,8 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)), + "ACPI-nvs", + "MMIO ", + "IO-ports", +- "PAL-code" ++ "PAL-code", ++ "persist ", + }; + if (desc->type < ARRAY_SIZE (types_str)) + grub_printf ("%s ", types_str[desc->type]); +@@ -87,21 +88,29 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)), + desc->physical_start + (desc->num_pages << 12) - 1, + desc->num_pages); + +- size = desc->num_pages; +- size <<= (12 - 10); +- if (size < 1024) +- grub_printf (" %4" PRIuGRUB_UINT64_T "KB", size); ++ size = desc->num_pages << 12; /* 4 KiB page size */ ++ /* ++ * Since size is a multiple of 4 KiB, no need to handle units ++ * of just Bytes (which would use a mask of 0x3ff). ++ * ++ * 14 characters would support the largest possible number of 4 KiB ++ * pages that are not a multiple of larger units (e.g., MiB): ++ * 17592186044415 (0xffffff_fffff000), but that uses a lot of ++ * whitespace for a rare case. 6 characters usually suffices; ++ * columns will be off if not, but this is preferable to rounding. ++ */ ++ if (size & 0xfffff) ++ grub_printf (" %6" PRIuGRUB_UINT64_T "KiB", size >> 10); ++ else if (size & 0x3fffffff) ++ grub_printf (" %6" PRIuGRUB_UINT64_T "MiB", size >> 20); ++ else if (size & 0xffffffffff) ++ grub_printf (" %6" PRIuGRUB_UINT64_T "GiB", size >> 30); ++ else if (size & 0x3ffffffffffff) ++ grub_printf (" %6" PRIuGRUB_UINT64_T "TiB", size >> 40); ++ else if (size & 0xfffffffffffffff) ++ grub_printf (" %6" PRIuGRUB_UINT64_T "PiB", size >> 50); + else +- { +- size /= 1024; +- if (size < 1024) +- grub_printf (" %4" PRIuGRUB_UINT64_T "MB", size); +- else +- { +- size /= 1024; +- grub_printf (" %4" PRIuGRUB_UINT64_T "GB", size); +- } +- } ++ grub_printf (" %6" PRIuGRUB_UINT64_T "EiB", size >> 60); + + attr = desc->attribute; + if (attr & GRUB_EFI_MEMORY_RUNTIME) +@@ -122,6 +131,12 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)), + grub_printf (" RP"); + if (attr & GRUB_EFI_MEMORY_XP) + grub_printf (" XP"); ++ if (attr & GRUB_EFI_MEMORY_NV) ++ grub_printf (" NV"); ++ if (attr & GRUB_EFI_MEMORY_MORE_RELIABLE) ++ grub_printf (" MR"); ++ if (attr & GRUB_EFI_MEMORY_RO) ++ grub_printf (" RO"); + + grub_printf ("\n"); + } +diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h +index 551d93e50a3..a6cce6e3395 100644 +--- a/include/grub/efi/api.h ++++ b/include/grub/efi/api.h +@@ -49,6 +49,9 @@ + #define GRUB_EFI_MEMORY_WP 0x0000000000001000LL + #define GRUB_EFI_MEMORY_RP 0x0000000000002000LL + #define GRUB_EFI_MEMORY_XP 0x0000000000004000LL ++#define GRUB_EFI_MEMORY_NV 0x0000000000008000LL ++#define GRUB_EFI_MEMORY_MORE_RELIABLE 0x0000000000010000LL ++#define GRUB_EFI_MEMORY_RO 0x0000000000020000LL + #define GRUB_EFI_MEMORY_RUNTIME 0x8000000000000000LL + + #define GRUB_EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 0x00000001 diff --git a/SOURCES/0194-efiemu-Handle-persistent-RAM-and-unknown-possible-fu.patch b/SOURCES/0194-efiemu-Handle-persistent-RAM-and-unknown-possible-fu.patch new file mode 100644 index 0000000..4f4b7f9 --- /dev/null +++ b/SOURCES/0194-efiemu-Handle-persistent-RAM-and-unknown-possible-fu.patch @@ -0,0 +1,84 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robert Elliott +Date: Fri, 22 Jan 2016 13:32:30 +0100 +Subject: [PATCH] efiemu: Handle persistent RAM and unknown possible future + additions. + +(cherry picked from commit ae3b83a4d4df75a01198a2fed7542391e7c449e0) + +Resolves: rhbz#1288608 +--- + grub-core/efiemu/mm.c | 25 ++++++++++++++++++++++--- + 1 file changed, 22 insertions(+), 3 deletions(-) + +diff --git a/grub-core/efiemu/mm.c b/grub-core/efiemu/mm.c +index d4a4f3aad6d..13af4ad0dd8 100644 +--- a/grub-core/efiemu/mm.c ++++ b/grub-core/efiemu/mm.c +@@ -99,7 +99,8 @@ grub_efiemu_request_memalign (grub_size_t align, grub_size_t size, + grub_size_t align_overhead; + struct grub_efiemu_memrequest *ret, *cur, *prev; + /* Check that the request is correct */ +- if (type >= GRUB_EFI_MAX_MEMORY_TYPE || type <= GRUB_EFI_LOADER_CODE) ++ if (type <= GRUB_EFI_LOADER_CODE || type == GRUB_EFI_PERSISTENT_MEMORY || ++ type >= GRUB_EFI_MAX_MEMORY_TYPE) + return -2; + + /* Add new size to requested size */ +@@ -166,6 +167,13 @@ efiemu_alloc_requests (void) + GRUB_EFI_MEMORY_MAPPED_IO, + GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE, + GRUB_EFI_PAL_CODE ++ ++ /* ++ * These are not allocatable: ++ * GRUB_EFI_RESERVED_MEMORY_TYPE ++ * GRUB_EFI_PERSISTENT_MEMORY ++ * >= GRUB_EFI_MAX_MEMORY_TYPE ++ */ + }; + + /* Compute total memory needed */ +@@ -402,6 +410,10 @@ fill_hook (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type, + return grub_efiemu_add_to_mmap (addr, size, + GRUB_EFI_ACPI_MEMORY_NVS); + ++ case GRUB_MEMORY_PRAM: ++ case GRUB_MEMORY_PMEM: ++ return grub_efiemu_add_to_mmap (addr, size, ++ GRUB_EFI_PERSISTENT_MEMORY); + default: + grub_dprintf ("efiemu", + "Unknown memory type %d. Assuming unusable\n", type); +@@ -445,7 +457,7 @@ grub_efiemu_mmap_iterate (grub_memory_hook_t hook, void *hook_data) + case GRUB_EFI_MEMORY_MAPPED_IO: + case GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE: + case GRUB_EFI_PAL_CODE: +- case GRUB_EFI_MAX_MEMORY_TYPE: ++ default: + hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, + GRUB_MEMORY_RESERVED, hook_data); + break; +@@ -468,6 +480,12 @@ grub_efiemu_mmap_iterate (grub_memory_hook_t hook, void *hook_data) + hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, + GRUB_MEMORY_NVS, hook_data); + break; ++ ++ case GRUB_EFI_PERSISTENT_MEMORY: ++ hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, ++ GRUB_MEMORY_PMEM, hook_data); ++ break; ++ + } + + return 0; +@@ -503,7 +521,8 @@ grub_efiemu_mmap_sort_and_uniq (void) + [GRUB_EFI_ACPI_MEMORY_NVS] = 3, + [GRUB_EFI_MEMORY_MAPPED_IO] = 4, + [GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE] = 4, +- [GRUB_EFI_PAL_CODE] = 4 ++ [GRUB_EFI_PAL_CODE] = 4, ++ [GRUB_EFI_PERSISTENT_MEMORY] = 4 + }; + + int i, j, k, done; diff --git a/SOURCES/0195-efiemu-Fix-compilation-failure.patch b/SOURCES/0195-efiemu-Fix-compilation-failure.patch new file mode 100644 index 0000000..40d83ed --- /dev/null +++ b/SOURCES/0195-efiemu-Fix-compilation-failure.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Fri, 22 Jan 2016 14:10:30 +0100 +Subject: [PATCH] efiemu: Fix compilation failure + +(cherry picked from commit b6a03dfd327489d53ee07c6d7d593b99c7b7cb62) + +Resolves: rhbz#1288608 +--- + grub-core/efiemu/mm.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/grub-core/efiemu/mm.c b/grub-core/efiemu/mm.c +index 13af4ad0dd8..e606dbffc92 100644 +--- a/grub-core/efiemu/mm.c ++++ b/grub-core/efiemu/mm.c +@@ -410,8 +410,8 @@ fill_hook (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type, + return grub_efiemu_add_to_mmap (addr, size, + GRUB_EFI_ACPI_MEMORY_NVS); + +- case GRUB_MEMORY_PRAM: +- case GRUB_MEMORY_PMEM: ++ case GRUB_MEMORY_PERSISTENT: ++ case GRUB_MEMORY_PERSISTENT_LEGACY: + return grub_efiemu_add_to_mmap (addr, size, + GRUB_EFI_PERSISTENT_MEMORY); + default: +@@ -483,7 +483,7 @@ grub_efiemu_mmap_iterate (grub_memory_hook_t hook, void *hook_data) + + case GRUB_EFI_PERSISTENT_MEMORY: + hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, +- GRUB_MEMORY_PMEM, hook_data); ++ GRUB_MEMORY_PERSISTENT, hook_data); + break; + + } diff --git a/SOURCES/0196-devmapper-getroot-use-makedev-instead-of-direct-shif.patch b/SOURCES/0196-devmapper-getroot-use-makedev-instead-of-direct-shif.patch new file mode 100644 index 0000000..fe265df --- /dev/null +++ b/SOURCES/0196-devmapper-getroot-use-makedev-instead-of-direct-shif.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Sat, 7 Nov 2015 09:46:46 +0300 +Subject: [PATCH] devmapper/getroot: use makedev instead of direct shift + +Fixes device detection with large number of devices. + +Reported by Tim Wallberg + +(cherry picked from commit 349a381df0ce2e809506f7b166bf952f97407330) + +Resolves: rhbz#1279599 +--- + grub-core/osdep/devmapper/getroot.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/grub-core/osdep/devmapper/getroot.c b/grub-core/osdep/devmapper/getroot.c +index d02386b3498..de32102322b 100644 +--- a/grub-core/osdep/devmapper/getroot.c ++++ b/grub-core/osdep/devmapper/getroot.c +@@ -204,8 +204,7 @@ grub_util_devmapper_part_to_disk (struct stat *st, + &major, &minor, 0)) + { + *is_part = 1; +- return grub_find_device ("/dev", +- (major << 8) | minor); ++ return grub_find_device ("/dev", makedev (major, minor)); + } + *is_part = 0; + return xstrdup (path); diff --git a/SOURCES/0197-loader-linux-do-not-pad-initrd-with-zeroes-at-the-en.patch b/SOURCES/0197-loader-linux-do-not-pad-initrd-with-zeroes-at-the-en.patch new file mode 100644 index 0000000..429a49c --- /dev/null +++ b/SOURCES/0197-loader-linux-do-not-pad-initrd-with-zeroes-at-the-en.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Thu, 7 May 2015 20:24:24 +0300 +Subject: [PATCH] loader/linux: do not pad initrd with zeroes at the end + +Syslinux memdisk is using initrd image and needs to know uncompressed +size in advance. For gzip uncompressed size is at the end of compressed +stream. Grub padded each input file to 4 bytes at the end, which means +syslinux got wrong size. + +Linux initramfs loader apparently does not care about trailing alignment. +So change code to align beginning of each file instead which atomatically +gives us the correct size for single file. + +Reported-By: David Shaw + +(cherry picked from commit a8c473288d3f0a5e17a903a5121dea1a695dda3b) + +Resolves: rhbz#1219864 +--- + grub-core/loader/linux.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c +index 117232f0c95..d2cd591f604 100644 +--- a/grub-core/loader/linux.c ++++ b/grub-core/loader/linux.c +@@ -161,6 +161,9 @@ grub_initrd_init (int argc, char *argv[], + for (i = 0; i < argc; i++) + { + const char *fname = argv[i]; ++ ++ initrd_ctx->size = ALIGN_UP (initrd_ctx->size, 4); ++ + if (grub_memcmp (argv[i], "newc:", 5) == 0) + { + const char *ptr, *eptr; +@@ -205,7 +208,7 @@ grub_initrd_init (int argc, char *argv[], + initrd_ctx->nfiles++; + initrd_ctx->components[i].size + = grub_file_size (initrd_ctx->components[i].file); +- initrd_ctx->size += ALIGN_UP (initrd_ctx->components[i].size, 4); ++ initrd_ctx->size += initrd_ctx->components[i].size; + } + + if (newc) +@@ -248,10 +251,12 @@ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx, + int i; + int newc = 0; + struct dir *root = 0; ++ grub_ssize_t cursize = 0; + + for (i = 0; i < initrd_ctx->nfiles; i++) + { +- grub_ssize_t cursize; ++ grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4)); ++ ptr += ALIGN_UP_OVERHEAD (cursize, 4); + + if (initrd_ctx->components[i].newc_name) + { +@@ -283,8 +288,6 @@ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx, + return grub_errno; + } + ptr += cursize; +- grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4)); +- ptr += ALIGN_UP_OVERHEAD (cursize, 4); + } + if (newc) + ptr = make_header (ptr, "TRAILER!!!", sizeof ("TRAILER!!!") - 1, 0, 0); diff --git a/SOURCES/0198-Revert-reopen-SNP-protocol-for-exclusive-use-by-grub.patch b/SOURCES/0198-Revert-reopen-SNP-protocol-for-exclusive-use-by-grub.patch new file mode 100644 index 0000000..11ffa6d --- /dev/null +++ b/SOURCES/0198-Revert-reopen-SNP-protocol-for-exclusive-use-by-grub.patch @@ -0,0 +1,73 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 7 Apr 2016 10:58:06 -0400 +Subject: [PATCH] Revert "reopen SNP protocol for exclusive use by grub" + +I *think* this should have been replaced by upstream's +49426e9fd2e562c73a4f1206f32eff9e424a1a73, so I'm reverting for now. + +May resolve rhbz#1273974. + +This reverts commit 147daeab22db793978f952b6f0d832919a1b0081. +--- + grub-core/net/drivers/efi/efinet.c | 40 -------------------------------------- + 1 file changed, 40 deletions(-) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index d8099a59855..3f112438a93 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -340,7 +340,6 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + { + struct grub_net_card *card; + grub_efi_device_path_t *dp; +- grub_efi_simple_network_t *net; + + dp = grub_efi_get_device_path (hnd); + if (! dp) +@@ -394,45 +393,6 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + &pxe_mode->dhcp_ack, + sizeof (pxe_mode->dhcp_ack), + 1, device, path); +- net = grub_efi_open_protocol (card->efi_handle, &net_io_guid, +- GRUB_EFI_OPEN_PROTOCOL_BY_EXCLUSIVE); +- if (net) { +- if (net->mode->state == GRUB_EFI_NETWORK_STOPPED +- && efi_call_1 (net->start, net) != GRUB_EFI_SUCCESS) +- continue; +- +- if (net->mode->state == GRUB_EFI_NETWORK_STOPPED) +- continue; +- +- if (net->mode->state == GRUB_EFI_NETWORK_STARTED +- && efi_call_3 (net->initialize, net, 0, 0) != GRUB_EFI_SUCCESS) +- continue; +- +- /* Enable hardware receive filters if driver declares support for it. +- We need unicast and broadcast and additionaly all nodes and +- solicited multicast for IPv6. Solicited multicast is per-IPv6 +- address and we currently do not have API to do it so simply +- try to enable receive of all multicast packets or evertyhing in +- the worst case (i386 PXE driver always enables promiscuous too). +- +- This does trust firmware to do what it claims to do. +- */ +- if (net->mode->receive_filter_mask) +- { +- grub_uint32_t filters = GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | +- GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST | +- GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; +- +- filters &= net->mode->receive_filter_mask; +- if (!(filters & GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST)) +- filters |= (net->mode->receive_filter_mask & +- GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS); +- +- efi_call_6 (net->receive_filters, net, filters, 0, 0, 0, NULL); +- } +- +- card->efi_net = net; +- } + return; + } + } diff --git a/SOURCES/0199-Add-a-url-parser.patch b/SOURCES/0199-Add-a-url-parser.patch new file mode 100644 index 0000000..f04ab41 --- /dev/null +++ b/SOURCES/0199-Add-a-url-parser.patch @@ -0,0 +1,1016 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 14 Jun 2016 16:18:44 -0400 +Subject: [PATCH] Add a url parser. + +This patch adds a url parser that can parse http, https, tftp, and tftps +urls, and is easily extensible to handle more types. + +It's a little ugly in terms of the arguments it takes. + +Signed-off-by: Peter Jones +--- + grub-core/Makefile.core.def | 1 + + grub-core/kern/misc.c | 13 + + grub-core/net/url.c | 856 ++++++++++++++++++++++++++++++++++++++++++++ + include/grub/misc.h | 45 +++ + include/grub/net/url.h | 28 ++ + 5 files changed, 943 insertions(+) + create mode 100644 grub-core/net/url.c + create mode 100644 include/grub/net/url.h + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 9378c732981..d73ea6f6c51 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -2103,6 +2103,7 @@ module = { + common = net/ethernet.c; + common = net/arp.c; + common = net/netbuff.c; ++ common = net/url.c; + }; + + module = { +diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c +index a3e5056db3f..392c697db03 100644 +--- a/grub-core/kern/misc.c ++++ b/grub-core/kern/misc.c +@@ -325,6 +325,19 @@ grub_strrchr (const char *s, int c) + return p; + } + ++char * ++grub_strchrnul (const char *s, int c) ++{ ++ do ++ { ++ if (*s == c) ++ break; ++ } ++ while (*s++); ++ ++ return (char *) s; ++} ++ + int + grub_strword (const char *haystack, const char *needle) + { +diff --git a/grub-core/net/url.c b/grub-core/net/url.c +new file mode 100644 +index 00000000000..537019f2c78 +--- /dev/null ++++ b/grub-core/net/url.c +@@ -0,0 +1,856 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2016 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifdef URL_TEST ++ ++#define _GNU_SOURCE 1 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define N_(x) x ++ ++#define grub_malloc(x) malloc(x) ++#define grub_free(x) ({if (x) free(x);}) ++#define grub_error(a, fmt, args...) printf(fmt "\n", ## args) ++#define grub_dprintf(a, fmt, args...) printf(a ": " fmt, ## args) ++#define grub_strlen(x) strlen(x) ++#define grub_strdup(x) strdup(x) ++#define grub_strstr(x,y) strstr(x,y) ++#define grub_memcpy(x,y,z) memcpy(x,y,z) ++#define grub_strcmp(x,y) strcmp(x,y) ++#define grub_strncmp(x,y,z) strncmp(x,y,z) ++#define grub_strcasecmp(x,y) strcasecmp(x,y) ++#define grub_strchrnul(x,y) strchrnul(x,y) ++#define grub_strchr(x,y) strchr(x,y) ++#define grub_strndup(x,y) strndup(x,y) ++#define grub_strtoul(x,y,z) strtoul(x,y,z) ++#define grub_memmove(x,y,z) memmove(x,y,z) ++#define grub_size_t size_t ++#define grub_errno errno ++ ++#else ++#include ++#include ++#include ++#include ++#endif ++ ++static char * ++translate_slashes(char *str) ++{ ++ int i, j; ++ if (str == NULL) ++ return str; ++ ++ for (i = 0, j = 0; str[i] != '\0'; i++, j++) ++ { ++ if (str[i] == '\\') ++ { ++ str[j] = '/'; ++ if (str[i+1] == '\\') ++ i++; ++ } ++ } ++ ++ return str; ++} ++ ++static inline int ++hex2int (char c) ++{ ++ if (c >= '0' && c <= '9') ++ return c - '0'; ++ c |= 0x20; ++ if (c >= 'a' && c <= 'f') ++ return c - 'a' + 10; ++ return -1; ++} ++ ++static int ++url_unescape (char *buf, grub_size_t len) ++{ ++ int c, rc; ++ unsigned int i; ++ ++ ++ if (len < 3) ++ { ++ for (i = 0; i < len; i++) ++ if (buf[i] == '%') ++ return -1; ++ return 0; ++ } ++ ++ for (i = 0; len > 2 && i < len - 2; i++) ++ { ++ if (buf[i] == '%') ++ { ++ unsigned int j; ++ for (j = i+1; j < i+3; j++) ++ { ++ if (!(buf[j] >= '0' && buf[j] <= '9') && ++ !(buf[j] >= 'a' && buf[j] <= 'f') && ++ !(buf[j] >= 'A' && buf[j] <= 'F')) ++ return -1; ++ } ++ i += 2; ++ } ++ } ++ if (i == len - 2) ++ { ++ if (buf[i+1] == '%' || buf[i+2] == '%') ++ return -1; ++ } ++ for (i = 0; i < len - 2; i++) ++ { ++ if (buf[i] == '%') ++ { ++ rc = hex2int (buf[i+1]); ++ if (rc < 0) ++ return -1; ++ c = (rc & 0xf) << 4; ++ rc = hex2int (buf[i+2]); ++ if (rc < 0) ++ return -1; ++ c |= (rc & 0xf); ++ ++ buf[i] = c; ++ grub_memmove (buf+i+1, buf+i+3, len-(i+2)); ++ len -= 2; ++ } ++ } ++ return 0; ++} ++ ++static int ++extract_http_url_info (char *url, int ssl, ++ char **userinfo, char **host, int *port, ++ char **file) ++{ ++ char *colon, *slash, *query, *at = NULL, *separator, *auth_end; ++ ++ char *userinfo_off = NULL; ++ char *userinfo_end; ++ char *host_off = NULL; ++ char *host_end; ++ char *port_off = NULL; ++ char *port_end; ++ char *file_off = NULL; ++ ++ grub_size_t l; ++ int c; ++ ++ if (!url || !userinfo || !host || !port || !file) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid argument"); ++ ++ *userinfo = *host = *file = NULL; ++ *port = -1; ++ ++ userinfo_off = url; ++ ++ slash = grub_strchrnul (userinfo_off, '/'); ++ query = grub_strchrnul (userinfo_off, '?'); ++ auth_end = slash < query ? slash : query; ++ /* auth_end here is one /past/ the last character in the auth section, i.e. ++ * it's the : or / or NUL */ ++ ++ separator = grub_strchrnul (userinfo_off, '@'); ++ if (separator > auth_end) ++ { ++ host_off = userinfo_off; ++ userinfo_off = NULL; ++ userinfo_end = NULL; ++ } ++ else ++ { ++ at = separator; ++ *separator = '\0'; ++ userinfo_end = separator; ++ host_off = separator + 1; ++ } ++ ++ if (*host_off == '[') ++ { ++ separator = grub_strchrnul (host_off, ']'); ++ if (separator >= auth_end) ++ goto fail; ++ ++ separator += 1; ++ host_end = separator; ++ } ++ else ++ { ++ host_end = separator = colon = grub_strchrnul (host_off, ':'); ++ ++ if (colon > auth_end) ++ { ++ separator = NULL; ++ host_end = auth_end; ++ } ++ } ++ ++ if (separator && separator < auth_end) ++ { ++ if (*separator == ':') ++ { ++ port_off = separator + 1; ++ port_end = auth_end; ++ ++ if (auth_end - port_end > 0) ++ goto fail; ++ if (port_end - port_off < 1) ++ goto fail; ++ } ++ else ++ goto fail; ++ } ++ ++ file_off = auth_end; ++ if (port_off) ++ { ++ unsigned long portul; ++ ++ separator = NULL; ++ c = *port_end; ++ *port_end = '\0'; ++ ++ portul = grub_strtoul (port_off, &separator, 10); ++ *port_end = c; ++#ifdef URL_TEST ++ if (portul == ULONG_MAX && errno == ERANGE) ++ goto fail; ++#else ++ if (grub_errno == GRUB_ERR_OUT_OF_RANGE) ++ goto fail; ++#endif ++ if (portul & ~0xfffful) ++ goto fail; ++ if (separator != port_end) ++ goto fail; ++ ++ *port = portul & 0xfffful; ++ } ++ else if (ssl) ++ *port = 443; ++ else ++ *port = 80; ++ ++ if (userinfo_off && *userinfo_off) ++ { ++ l = userinfo_end - userinfo_off + 1; ++ ++ *userinfo = grub_strndup (userinfo_off, l); ++ if (!*userinfo) ++ goto fail; ++ (*userinfo)[l-1]= '\0'; ++ } ++ ++ l = host_end - host_off; ++ c = *host_end; ++ *host_end = '\0'; ++ *host = grub_strndup (host_off, l); ++ *host_end = c; ++ if (!*host) ++ goto fail; ++ (*host)[l] = '\0'; ++ ++ *file = grub_strdup (file_off); ++ if (!*file) ++ goto fail; ++ ++ if (at) ++ *at = '@'; ++ return 0; ++fail: ++ if (at) ++ *at = '@'; ++ grub_free (*userinfo); ++ grub_free (*host); ++ grub_free (*file); ++ ++ return -1; ++} ++ ++static int ++extract_tftp_url_info (char *url, int ssl, char **host, char **file, int *port) ++{ ++ char *slash, *semi; ++ ++ char *host_off = url; ++ char *host_end; ++ char *file_off; ++ ++ int c; ++ ++ if (!url || !host || !file || !port) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid argument"); ++ ++ if (ssl) ++ *port = 3713; ++ else ++ *port = 69; ++ ++ slash = grub_strchr (url, '/'); ++ if (!slash) ++ return -1; ++ ++ host_end = file_off = slash; ++ ++ semi = grub_strchrnul (slash, ';'); ++ if (!grub_strncmp (semi, ";mode=", 6) && grub_strcmp (semi+6, "octet")) ++ { ++ grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, ++ N_("TFTP mode `%s' is not implemented."), semi+6); ++ return -1; ++ } ++ ++ /* ++ * Maybe somebody added a new method, I dunno. Anyway, semi is a reserved ++ * character, so if it's there, it's the start of the mode block or it's ++ * invalid. So set it to \0 unconditionally, not just for ;mode=octet ++ */ ++ *semi = '\0'; ++ ++ c = *host_end; ++ *host_end = '\0'; ++ *host = grub_strdup (host_off); ++ *host_end = c; ++ ++ *file = grub_strdup (file_off); ++ ++ if (!*file || !*host) ++ { ++ grub_free (*file); ++ grub_free (*host); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int ++extract_url_info (const char *urlbuf, grub_size_t buflen, ++ char **scheme, char **userinfo, ++ char **host, int *port, char **file) ++{ ++ char *url; ++ char *colon; ++ ++ char *scheme_off; ++ char *specific_off; ++ ++ int rc; ++ int c; ++ ++ int https; ++ ++ if (!urlbuf || !buflen || !scheme || !userinfo || !host || !port || !file) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid argument"); ++ ++ *scheme = *userinfo = *host = *file = NULL; ++ *port = -1; ++ ++ /* make sure we have our own coherent grub_string. */ ++ url = grub_malloc (buflen + 1); ++ if (!url) ++ return -1; ++ ++ grub_memcpy (url, urlbuf, buflen); ++ url[buflen] = '\0'; ++ ++ grub_dprintf ("net", "dhcpv6 boot-file-url: `%s'\n", url); ++ ++ /* get rid of any backslashes */ ++ url = translate_slashes (url); ++ ++ /* find the constituent parts */ ++ colon = grub_strstr (url, "://"); ++ if (!colon) ++ goto fail; ++ ++ scheme_off = url; ++ c = *colon; ++ *colon = '\0'; ++ specific_off = colon + 3; ++ ++ https = !grub_strcasecmp (scheme_off, "https"); ++ ++ rc = 0; ++ if (!grub_strcasecmp (scheme_off, "tftp")) ++ { ++ rc = extract_tftp_url_info (specific_off, 0, host, file, port); ++ } ++#ifdef URL_TEST ++ else if (!grub_strcasecmp (scheme_off, "http") || https) ++#else ++ else if (!grub_strcasecmp (scheme_off, "http")) ++#endif ++ { ++ rc = extract_http_url_info (specific_off, ++ https, userinfo, host, port, file); ++ } ++#ifdef URL_TEST ++ else if (!grub_strcasecmp (scheme_off, "iscsi")) ++ { ++ grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, ++ N_("Unimplemented URL scheme `%s'"), scheme_off); ++ *colon = c; ++ goto fail; ++ } ++ else if (!grub_strcasecmp (scheme_off, "tftps")) ++ { ++ rc = extract_tftp_url_info (specific_off, 1, host, file, port); ++ } ++#endif ++ else ++ { ++ grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, ++ N_("Unimplemented URL scheme `%s'"), scheme_off); ++ *colon = c; ++ goto fail; ++ } ++ ++ if (rc < 0) ++ { ++ *colon = c; ++ goto fail; ++ } ++ ++ *scheme = grub_strdup (scheme_off); ++ *colon = c; ++ if (!*scheme) ++ goto fail; ++ ++ if (*userinfo) ++ { ++ rc = url_unescape (*userinfo, grub_strlen (*userinfo)); ++ if (rc < 0) ++ goto fail; ++ } ++ ++ if (*host) ++ { ++ rc = url_unescape (*host, grub_strlen (*host)); ++ if (rc < 0) ++ goto fail; ++ } ++ ++ if (*file) ++ { ++ rc = url_unescape (*file, grub_strlen (*file)); ++ if (rc < 0) ++ goto fail; ++ } ++ ++ grub_free (url); ++ return 0; ++fail: ++ grub_free (*scheme); ++ grub_free (*userinfo); ++ grub_free (*host); ++ grub_free (*file); ++ ++ if (!grub_errno) ++ grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("Invalid boot-file-url `%s'"), ++ url); ++ grub_free (url); ++ return -1; ++} ++ ++#ifdef URL_TEST ++ ++struct test { ++ char *url; ++ int rc; ++ char *scheme; ++ char *userinfo; ++ char *host; ++ int port; ++ char *file; ++} tests[] = { ++ {.url = "http://foo.example.com/", ++ .rc = 0, ++ .scheme = "http", ++ .host = "foo.example.com", ++ .port = 80, ++ .file = "/", ++ }, ++ {.url = "http://foo.example.com/?foobar", ++ .rc = 0, ++ .scheme = "http", ++ .host = "foo.example.com", ++ .port = 80, ++ .file = "/?foobar", ++ }, ++ {.url = "http://[foo.example.com/", ++ .rc = -1, ++ }, ++ {.url = "http://[foo.example.com/?foobar", ++ .rc = -1, ++ }, ++ {.url = "http://foo.example.com:/", ++ .rc = -1, ++ }, ++ {.url = "http://foo.example.com:81/", ++ .rc = 0, ++ .scheme = "http", ++ .host = "foo.example.com", ++ .port = 81, ++ .file = "/", ++ }, ++ {.url = "http://foo.example.com:81/?foobar", ++ .rc = 0, ++ .scheme = "http", ++ .host = "foo.example.com", ++ .port = 81, ++ .file = "/?foobar", ++ }, ++ {.url = "http://[1234::1]/", ++ .rc = 0, ++ .scheme = "http", ++ .host = "[1234::1]", ++ .port = 80, ++ .file = "/", ++ }, ++ {.url = "http://[1234::1]/?foobar", ++ .rc = 0, ++ .scheme = "http", ++ .host = "[1234::1]", ++ .port = 80, ++ .file = "/?foobar", ++ }, ++ {.url = "http://[1234::1]:81/", ++ .rc = 0, ++ .scheme = "http", ++ .host = "[1234::1]", ++ .port = 81, ++ .file = "/", ++ }, ++ {.url = "http://[1234::1]:81/?foobar", ++ .rc = 0, ++ .scheme = "http", ++ .host = "[1234::1]", ++ .port = 81, ++ .file = "/?foobar", ++ }, ++ {.url = "http://foo@foo.example.com/", ++ .rc = 0, ++ .scheme = "http", ++ .userinfo = "foo", ++ .host = "foo.example.com", ++ .port = 80, ++ .file = "/", ++ }, ++ {.url = "http://foo@foo.example.com/?foobar", ++ .rc = 0, ++ .scheme = "http", ++ .userinfo = "foo", ++ .host = "foo.example.com", ++ .port = 80, ++ .file = "/?foobar", ++ }, ++ {.url = "http://foo@[foo.example.com/", ++ .rc = -1, ++ }, ++ {.url = "http://foo@[foo.example.com/?foobar", ++ .rc = -1, ++ }, ++ {.url = "http://foo@foo.example.com:81/", ++ .rc = 0, ++ .scheme = "http", ++ .userinfo = "foo", ++ .host = "foo.example.com", ++ .port = 81, ++ .file = "/", ++ }, ++ {.url = "http://foo@foo.example.com:81/?foobar", ++ .rc = 0, ++ .scheme = "http", ++ .userinfo = "foo", ++ .host = "foo.example.com", ++ .port = 81, ++ .file = "/?foobar", ++ }, ++ {.url = "http://foo@[1234::1]/", ++ .rc = 0, ++ .scheme = "http", ++ .userinfo = "foo", ++ .host = "[1234::1]", ++ .port = 80, ++ .file = "/", ++ }, ++ {.url = "http://foo@[1234::1]/?foobar", ++ .rc = 0, ++ .scheme = "http", ++ .userinfo = "foo", ++ .host = "[1234::1]", ++ .port = 80, ++ .file = "/?foobar", ++ }, ++ {.url = "http://foo@[1234::1]:81/", ++ .rc = 0, ++ .scheme = "http", ++ .userinfo = "foo", ++ .host = "[1234::1]", ++ .port = 81, ++ .file = "/", ++ }, ++ {.url = "http://foo@[1234::1]:81/?foobar", ++ .rc = 0, ++ .scheme = "http", ++ .userinfo = "foo", ++ .host = "[1234::1]", ++ .port = 81, ++ .file = "/?foobar", ++ }, ++ {.url = "https://foo.example.com/", ++ .rc = 0, ++ .scheme = "https", ++ .host = "foo.example.com", ++ .port = 443, ++ .file = "/", ++ }, ++ {.url = "https://foo.example.com/?foobar", ++ .rc = 0, ++ .scheme = "https", ++ .host = "foo.example.com", ++ .port = 443, ++ .file = "/?foobar", ++ }, ++ {.url = "https://[foo.example.com/", ++ .rc = -1, ++ }, ++ {.url = "https://[foo.example.com/?foobar", ++ .rc = -1, ++ }, ++ {.url = "https://foo.example.com:81/", ++ .rc = 0, ++ .scheme = "https", ++ .host = "foo.example.com", ++ .port = 81, ++ .file = "/", ++ }, ++ {.url = "https://foo.example.com:81/?foobar", ++ .rc = 0, ++ .scheme = "https", ++ .host = "foo.example.com", ++ .port = 81, ++ .file = "/?foobar", ++ }, ++ {.url = "https://[1234::1]/", ++ .rc = 0, ++ .scheme = "https", ++ .host = "[1234::1]", ++ .port = 443, ++ .file = "/", ++ }, ++ {.url = "https://[1234::1]/?foobar", ++ .rc = 0, ++ .scheme = "https", ++ .host = "[1234::1]", ++ .port = 443, ++ .file = "/?foobar", ++ }, ++ {.url = "https://[1234::1]:81/", ++ .rc = 0, ++ .scheme = "https", ++ .host = "[1234::1]", ++ .port = 81, ++ .file = "/", ++ }, ++ {.url = "https://[1234::1]:81/?foobar", ++ .rc = 0, ++ .scheme = "https", ++ .host = "[1234::1]", ++ .port = 81, ++ .file = "/?foobar", ++ }, ++ {.url = "https://foo@foo.example.com/", ++ .rc = 0, ++ .scheme = "https", ++ .userinfo = "foo", ++ .host = "foo.example.com", ++ .port = 443, ++ .file = "/", ++ }, ++ {.url = "https://foo@foo.example.com/?foobar", ++ .rc = 0, ++ .scheme = "https", ++ .userinfo = "foo", ++ .host = "foo.example.com", ++ .port = 443, ++ .file = "/?foobar", ++ }, ++ {.url = "https://foo@[foo.example.com/", ++ .rc = -1, ++ }, ++ {.url = "https://f%6fo@[foo.example.com/?fooba%72", ++ .rc = -1, ++ }, ++ {.url = "https://foo@foo.example.com:81/", ++ .rc = 0, ++ .scheme = "https", ++ .userinfo = "foo", ++ .host = "foo.example.com", ++ .port = 81, ++ .file = "/", ++ }, ++ {.url = "https://foo@foo.example.com:81/?foobar", ++ .rc = 0, ++ .scheme = "https", ++ .userinfo = "foo", ++ .host = "foo.example.com", ++ .port = 81, ++ .file = "/?foobar", ++ }, ++ {.url = "https://foo@[1234::1]/", ++ .rc = 0, ++ .scheme = "https", ++ .userinfo = "foo", ++ .host = "[1234::1]", ++ .port = 443, ++ .file = "/", ++ }, ++ {.url = "https://foo@[1234::1]/?foobar", ++ .rc = 0, ++ .scheme = "https", ++ .userinfo = "foo", ++ .host = "[1234::1]", ++ .port = 443, ++ .file = "/?foobar", ++ }, ++ {.url = "https://f%6fo@[12%334::1]:81/", ++ .rc = 0, ++ .scheme = "https", ++ .userinfo = "foo", ++ .host = "[1234::1]", ++ .port = 81, ++ .file = "/", ++ }, ++ {.url = "https://foo@[1234::1]:81/?foobar", ++ .rc = 0, ++ .scheme = "https", ++ .userinfo = "foo", ++ .host = "[1234::1]", ++ .port = 81, ++ .file = "/?foobar", ++ }, ++ {.url = "tftp://foo.e%78ample.com/foo/bar/b%61%7a", ++ .rc = 0, ++ .scheme = "tftp", ++ .host = "foo.example.com", ++ .port = 69, ++ .file = "/foo/bar/baz", ++ }, ++ {.url = "tftp://foo.example.com/foo/bar/baz", ++ .rc = 0, ++ .scheme = "tftp", ++ .host = "foo.example.com", ++ .port = 69, ++ .file = "/foo/bar/baz", ++ }, ++ {.url = "tftps://foo.example.com/foo/bar/baz", ++ .rc = 0, ++ .scheme = "tftps", ++ .host = "foo.example.com", ++ .port = 3713, ++ .file = "/foo/bar/baz", ++ }, ++ {.url = "tftps://foo.example.com/foo/bar/baz;mode=netascii", ++ .rc = -1, ++ }, ++ {.url = "tftps://foo.example.com/foo/bar/baz;mode=octet", ++ .rc = 0, ++ .scheme = "tftps", ++ .host = "foo.example.com", ++ .port = 3713, ++ .file = "/foo/bar/baz", ++ }, ++ {.url = "tftps://foo.example.com/foo/bar/baz;mode=invalid", ++ .rc = -1, ++ }, ++ {.url = "", ++ }, ++}; ++ ++static int ++string_test (char *name, char *a, char *b) ++{ ++ if ((a && !b) || (!a && b)) ++ { ++ printf("expected %s \"%s\", got \"%s\"\n", name, a, b); ++ return -1; ++ } ++ if (a && b && strcmp(a, b)) ++ { ++ printf("expected %s \"%s\", got \"%s\"\n", name, a, b); ++ return -1; ++ } ++ return 0; ++} ++ ++int ++main(void) ++{ ++ unsigned int i; ++ int rc; ++ ++ for (i = 0; tests[i].url[0] != '\0'; i++) ++ { ++ char *scheme, *userinfo, *host, *file; ++ int port; ++ ++ printf("======= url: \"%s\"\n", tests[i].url); ++ rc = extract_url_info(tests[i].url, strlen(tests[i].url) + 1, ++ &scheme, &userinfo, &host, &port, &file); ++ if (tests[i].rc != rc) ++ { ++ printf(" extract_url_info(...) = %d\n", rc); ++ exit(1); ++ } ++ else if (rc >= 0) ++ { ++ if (string_test("scheme", tests[i].scheme, scheme) < 0) ++ exit(1); ++ if (string_test("userinfo", tests[i].userinfo, userinfo) < 0) ++ exit(1); ++ if (string_test("host", tests[i].host, host) < 0) ++ exit(1); ++ if (port != tests[i].port) ++ { ++ printf(" bad port \"%d\" should have been \"%d\"\n", ++ port, tests[i].port); ++ exit(1); ++ } ++ if (string_test("file", tests[i].file, file) < 0) ++ exit(1); ++ } ++ free(scheme); ++ free(userinfo); ++ free(host); ++ free(file); ++ } ++ printf("everything worked?!?\n"); ++} ++#endif +diff --git a/include/grub/misc.h b/include/grub/misc.h +index c6cd4564d86..34250291908 100644 +--- a/include/grub/misc.h ++++ b/include/grub/misc.h +@@ -104,6 +104,7 @@ int EXPORT_FUNC(grub_strncmp) (const char *s1, const char *s2, grub_size_t n); + + char *EXPORT_FUNC(grub_strchr) (const char *s, int c); + char *EXPORT_FUNC(grub_strrchr) (const char *s, int c); ++char *EXPORT_FUNC(grub_strchrnul) (const char *s, int c); + int EXPORT_FUNC(grub_strword) (const char *s, const char *w); + + /* Copied from gnulib. +@@ -226,6 +227,50 @@ grub_toupper (int c) + return c; + } + ++static inline char * ++grub_strcasestr (const char *haystack, const char *needle) ++{ ++ /* Be careful not to look at the entire extent of haystack or needle ++ until needed. This is useful because of these two cases: ++ - haystack may be very long, and a match of needle found early, ++ - needle may be very long, and not even a short initial segment of ++ needle may be found in haystack. */ ++ if (*needle != '\0') ++ { ++ /* Speed up the following searches of needle by caching its first ++ character. */ ++ char b = *needle++; ++ ++ for (;; haystack++) ++ { ++ if (*haystack == '\0') ++ /* No match. */ ++ return 0; ++ if (grub_tolower(*haystack) == grub_tolower(b)) ++ /* The first character matches. */ ++ { ++ const char *rhaystack = haystack + 1; ++ const char *rneedle = needle; ++ ++ for (;; rhaystack++, rneedle++) ++ { ++ if (*rneedle == '\0') ++ /* Found a match. */ ++ return (char *) haystack; ++ if (*rhaystack == '\0') ++ /* No match. */ ++ return 0; ++ if (grub_tolower(*rhaystack) != grub_tolower(*rneedle)) ++ /* Nothing in this round. */ ++ break; ++ } ++ } ++ } ++ } ++ else ++ return (char *) haystack; ++} ++ + static inline int + grub_strcasecmp (const char *s1, const char *s2) + { +diff --git a/include/grub/net/url.h b/include/grub/net/url.h +new file mode 100644 +index 00000000000..a215fa27d0a +--- /dev/null ++++ b/include/grub/net/url.h +@@ -0,0 +1,28 @@ ++/* url.h - prototypes for url parsing functions */ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2016 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_URL_HEADER ++#define GRUB_URL_HEADER 1 ++ ++int ++EXPORT_FUNC(extract_url_info) (const char *urlbuf, grub_size_t buflen, ++ char **scheme, char **userinfo, ++ char **host, int *port, char **file); ++ ++#endif /* GRUB_URL_HEADER */ diff --git a/SOURCES/0200-efinet-and-bootp-add-support-for-dhcpv6.patch b/SOURCES/0200-efinet-and-bootp-add-support-for-dhcpv6.patch new file mode 100644 index 0000000..b2a0d52 --- /dev/null +++ b/SOURCES/0200-efinet-and-bootp-add-support-for-dhcpv6.patch @@ -0,0 +1,652 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 8 Jun 2016 21:03:37 -0400 +Subject: [PATCH] efinet and bootp: add support for dhcpv6 + +Signed-off-by: Peter Jones +--- + grub-core/net/bootp.c | 173 +++++++++++++++++++++++++++++++++++++ + grub-core/net/drivers/efi/efinet.c | 52 +++++++++-- + grub-core/net/net.c | 67 ++++++++++++++ + grub-core/net/tftp.c | 4 + + include/grub/efi/api.h | 129 +++++++++++++++++++++++++-- + include/grub/net.h | 60 +++++++++++++ + 6 files changed, 471 insertions(+), 14 deletions(-) + +diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c +index 88f20568914..4793ebc434e 100644 +--- a/grub-core/net/bootp.c ++++ b/grub-core/net/bootp.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + #include + + static char * +@@ -335,6 +336,178 @@ grub_net_configure_by_dhcp_ack (const char *name, + return inter; + } + ++struct grub_net_network_level_interface * ++grub_net_configure_by_dhcpv6_ack (const char *name, ++ struct grub_net_card *card, ++ grub_net_interface_flags_t flags ++ __attribute__((__unused__)), ++ const grub_net_link_level_address_t *hwaddr, ++ const struct grub_net_dhcpv6_packet *packet, ++ int is_def, char **device, char **path) ++{ ++ struct grub_net_network_level_interface *inter = NULL; ++ struct grub_net_network_level_address addr; ++ int mask = -1; ++ ++ if (device) ++ *device = 0; ++ if (path) ++ *path = 0; ++ ++ grub_dprintf ("net", "mac address is %02x:%02x:%02x:%02x:%02x:%02x\n", ++ hwaddr->mac[0], hwaddr->mac[1], hwaddr->mac[2], ++ hwaddr->mac[3], hwaddr->mac[4], hwaddr->mac[5]); ++ ++ if (is_def) ++ grub_net_default_server = 0; ++ ++ if (is_def && !grub_net_default_server && packet) ++ { ++ const grub_uint8_t *options = packet->dhcp_options; ++ unsigned int option_max = 1024 - OFFSET_OF (dhcp_options, packet); ++ unsigned int i; ++ ++ for (i = 0; i < option_max - sizeof (grub_net_dhcpv6_option_t); ) ++ { ++ grub_uint16_t num, len; ++ grub_net_dhcpv6_option_t *opt = ++ (grub_net_dhcpv6_option_t *)(options + i); ++ ++ num = grub_be_to_cpu16(opt->option_num); ++ len = grub_be_to_cpu16(opt->option_len); ++ ++ grub_dprintf ("net", "got dhcpv6 option %d len %d\n", num, len); ++ ++ if (len == 0) ++ break; ++ ++ if (len + i > 1024) ++ break; ++ ++ if (num == GRUB_NET_DHCP6_BOOTFILE_URL) ++ { ++ char *scheme, *userinfo, *host, *file; ++ char *tmp; ++ int hostlen; ++ int port; ++ int rc = extract_url_info ((const char *)opt->option_data, ++ (grub_size_t)len, ++ &scheme, &userinfo, &host, &port, ++ &file); ++ if (rc < 0) ++ continue; ++ ++ /* right now this only handles tftp. */ ++ if (grub_strcmp("tftp", scheme)) ++ { ++ grub_free (scheme); ++ grub_free (userinfo); ++ grub_free (host); ++ grub_free (file); ++ continue; ++ } ++ grub_free (userinfo); ++ ++ hostlen = grub_strlen (host); ++ if (hostlen > 2 && host[0] == '[' && host[hostlen-1] == ']') ++ { ++ tmp = host+1; ++ host[hostlen-1] = '\0'; ++ } ++ else ++ tmp = host; ++ ++ *device = grub_xasprintf ("%s,%s", scheme, tmp); ++ grub_free (scheme); ++ grub_free (host); ++ ++ if (file && *file) ++ { ++ tmp = grub_strrchr (file, '/'); ++ if (tmp) ++ *(tmp+1) = '\0'; ++ else ++ file[0] = '\0'; ++ } ++ else if (!file) ++ file = grub_strdup (""); ++ ++ if (file[0] == '/') ++ { ++ *path = grub_strdup (file+1); ++ grub_free (file); ++ } ++ else ++ *path = file; ++ } ++ else if (num == GRUB_NET_DHCP6_IA_NA) ++ { ++ const grub_net_dhcpv6_option_t *ia_na_opt; ++ const grub_net_dhcpv6_opt_ia_na_t *ia_na = ++ (const grub_net_dhcpv6_opt_ia_na_t *)opt; ++ unsigned int left = len - OFFSET_OF (options, ia_na); ++ unsigned int j; ++ ++ if ((grub_uint8_t *)ia_na + left > ++ (grub_uint8_t *)options + option_max) ++ left -= ((grub_uint8_t *)ia_na + left) ++ - ((grub_uint8_t *)options + option_max); ++ ++ if (len < OFFSET_OF (option_data, opt) ++ + sizeof (grub_net_dhcpv6_option_t)) ++ { ++ grub_dprintf ("net", ++ "found dhcpv6 ia_na option with no address\n"); ++ continue; ++ } ++ ++ for (j = 0; left > sizeof (grub_net_dhcpv6_option_t); ) ++ { ++ ia_na_opt = (const grub_net_dhcpv6_option_t *) ++ (ia_na->options + j); ++ grub_uint16_t ia_na_opt_num, ia_na_opt_len; ++ ++ ia_na_opt_num = grub_be_to_cpu16 (ia_na_opt->option_num); ++ ia_na_opt_len = grub_be_to_cpu16 (ia_na_opt->option_len); ++ if (ia_na_opt_len == 0) ++ break; ++ if (j + ia_na_opt_len > left) ++ break; ++ if (ia_na_opt_num == GRUB_NET_DHCP6_IA_ADDRESS) ++ { ++ const grub_net_dhcpv6_opt_ia_address_t *ia_addr; ++ ++ ia_addr = (const grub_net_dhcpv6_opt_ia_address_t *) ++ ia_na_opt; ++ addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; ++ grub_memcpy(addr.ipv6, ia_addr->ipv6_address, ++ sizeof (ia_addr->ipv6_address)); ++ inter = grub_net_add_addr (name, card, &addr, hwaddr, 0); ++ } ++ ++ j += ia_na_opt_len; ++ left -= ia_na_opt_len; ++ } ++ } ++ ++ i += len + 4; ++ } ++ ++ grub_print_error (); ++ } ++ ++ if (is_def) ++ { ++ grub_env_set ("net_default_interface", name); ++ grub_env_export ("net_default_interface"); ++ } ++ ++ if (inter) ++ grub_net_add_ipv6_local (inter, mask); ++ return inter; ++} ++ ++ + void + grub_net_process_dhcp (struct grub_net_buff *nb, + struct grub_net_card *card) +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index 3f112438a93..d7befb2ba9b 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -18,11 +18,15 @@ + + #include + #include ++#include + #include ++#include + #include + #include + #include + #include ++#include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -339,7 +343,7 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + char **path) + { + struct grub_net_card *card; +- grub_efi_device_path_t *dp; ++ grub_efi_device_path_t *dp, *ldp = NULL; + + dp = grub_efi_get_device_path (hnd); + if (! dp) +@@ -350,14 +354,19 @@ 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; ++ + if (card->driver != &efidriver) + continue; ++ + cdp = grub_efi_get_device_path (card->efi_handle); + if (! cdp) + continue; ++ ++ ldp = grub_efi_find_last_device_path (dp); ++ + if (grub_efi_compare_device_paths (dp, cdp) != 0) + { +- grub_efi_device_path_t *ldp, *dup_dp, *dup_ldp; ++ grub_efi_device_path_t *dup_dp, *dup_ldp; + int match; + + /* EDK2 UEFI PXE driver creates pseudo devices with type IPv4/IPv6 +@@ -366,7 +375,6 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + devices. We skip them when enumerating cards, so here we need to + find matching MAC 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)) +@@ -383,16 +391,44 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + if (!match) + continue; + } ++ + pxe = grub_efi_open_protocol (hnd, &pxe_io_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); + 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_link_level_address_t hwaddr; ++ ++ grub_dprintf ("efinet", "using ipv6 and dhcpv6\n"); ++ grub_dprintf ("efinet", "dhcp_ack_received: %s%s\n", ++ pxe_mode->dhcp_ack_received ? "yes" : "no", ++ pxe_mode->dhcp_ack_received ? "" : " cannot continue"); ++ if (!pxe_mode->dhcp_ack_received) ++ continue; ++ ++ hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; ++ grub_memcpy (hwaddr.mac, ++ card->efi_net->mode->current_address, ++ sizeof (hwaddr.mac)); ++ ++ grub_net_configure_by_dhcpv6_ack (card->name, card, 0, ++ &hwaddr, &pxe_mode->dhcp_ack, ++ 1, device, path); ++ grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path); ++ } ++ else ++ { ++ grub_dprintf ("efinet", "using ipv4 and dhcp\n"); ++ 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); ++ grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path); ++ } + return; + } + } +diff --git a/grub-core/net/net.c b/grub-core/net/net.c +index b10addbe27b..81d3b6208cb 100644 +--- a/grub-core/net/net.c ++++ b/grub-core/net/net.c +@@ -969,6 +969,73 @@ grub_net_network_level_interface_register (struct grub_net_network_level_interfa + grub_net_network_level_interfaces = inter; + } + ++int ++grub_ipv6_get_masksize(grub_uint8_t *be_mask) ++{ ++ grub_uint8_t *mask; ++ grub_uint16_t mask16[8]; ++ unsigned int x; ++ int ret = 0; ++ ++ grub_memcpy (mask16, be_mask, sizeof(mask16)); ++ for (x = 0; x < 8; x++) ++ mask16[x] = grub_be_to_cpu16 (mask16[x]); ++ ++ mask = (grub_uint8_t *)mask16; ++ ++ for (x = 15; x > 0; x++) ++ { ++ grub_uint8_t octet = mask[x]; ++ while (octet & 0x80) ++ { ++ ret++; ++ octet <<= 1; ++ } ++ if (ret) ++ ret += 8 * (15 - x); ++ break; ++ } ++ ++ return ret; ++} ++ ++grub_err_t ++grub_net_add_ipv6_local (struct grub_net_network_level_interface *inter, ++ int mask) ++{ ++ struct grub_net_route *route; ++ ++ if (inter->address.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6) ++ return 0; ++ ++ if (mask == -1) ++ mask = grub_ipv6_get_masksize ((grub_uint8_t *)inter->address.ipv6); ++ ++ if (mask == -1) ++ return 0; ++ ++ route = grub_zalloc (sizeof (*route)); ++ if (!route) ++ return grub_errno; ++ ++ route->name = grub_xasprintf ("%s:local", inter->name); ++ if (!route->name) ++ { ++ grub_free (route); ++ return grub_errno; ++ } ++ ++ route->target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; ++ grub_memcpy (route->target.ipv6.base, inter->address.ipv6, ++ sizeof (inter->address.ipv6)); ++ route->target.ipv6.masksize = mask; ++ route->is_gateway = 0; ++ route->interface = inter; ++ ++ grub_net_route_register (route); ++ ++ return 0; ++} + + grub_err_t + grub_net_add_ipv4_local (struct grub_net_network_level_interface *inter, +diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c +index 51736142764..22a4debdcd4 100644 +--- a/grub-core/net/tftp.c ++++ b/grub-core/net/tftp.c +@@ -370,18 +370,22 @@ tftp_open (struct grub_file *file, const char *filename) + if (!data->pq) + return grub_errno; + ++ grub_dprintf("tftp", "resolving address for %s\n", file->device->net->server); + err = grub_net_resolve_address (file->device->net->server, &addr); + if (err) + { ++ grub_dprintf("tftp", "Address resolution failed: %d\n", err); + destroy_pq (data); + return err; + } + ++ grub_dprintf("tftp", "opening connection\n"); + data->sock = grub_net_udp_open (addr, + TFTP_SERVER_PORT, tftp_receive, + file); + if (!data->sock) + { ++ grub_dprintf("tftp", "connection failed\n"); + destroy_pq (data); + return grub_errno; + } +diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h +index a6cce6e3395..9422ba9a9db 100644 +--- a/include/grub/efi/api.h ++++ b/include/grub/efi/api.h +@@ -527,10 +527,16 @@ typedef void *grub_efi_handle_t; + typedef void *grub_efi_event_t; + typedef grub_efi_uint64_t grub_efi_lba_t; + typedef grub_efi_uintn_t grub_efi_tpl_t; +-typedef grub_uint8_t grub_efi_mac_address_t[32]; +-typedef grub_uint8_t grub_efi_ipv4_address_t[4]; +-typedef grub_uint16_t grub_efi_ipv6_address_t[8]; +-typedef grub_uint8_t grub_efi_ip_address_t[8] __attribute__ ((aligned(4))); ++typedef grub_efi_uint8_t grub_efi_mac_address_t[32]; ++typedef grub_efi_uint8_t grub_efi_ipv4_address_t[4]; ++typedef grub_efi_uint8_t grub_efi_ipv6_address_t[16]; ++typedef union ++{ ++ grub_efi_uint32_t addr[4]; ++ grub_efi_ipv4_address_t v4; ++ grub_efi_ipv6_address_t v6; ++} grub_efi_ip_address_t __attribute__ ((aligned(4))); ++ + typedef grub_efi_uint64_t grub_efi_physical_address_t; + typedef grub_efi_uint64_t grub_efi_virtual_address_t; + +@@ -1405,16 +1411,127 @@ struct grub_efi_simple_text_output_interface + }; + typedef struct grub_efi_simple_text_output_interface grub_efi_simple_text_output_interface_t; + +-typedef grub_uint8_t grub_efi_pxe_packet_t[1472]; ++typedef struct grub_efi_pxe_dhcpv4_packet ++{ ++ grub_efi_uint8_t bootp_opcode; ++ grub_efi_uint8_t bootp_hwtype; ++ grub_efi_uint8_t bootp_hwaddr_len; ++ grub_efi_uint8_t bootp_gate_hops; ++ grub_efi_uint32_t bootp_ident; ++ grub_efi_uint16_t bootp_seconds; ++ grub_efi_uint16_t bootp_flags; ++ grub_efi_uint8_t bootp_ci_addr[4]; ++ grub_efi_uint8_t bootp_yi_addr[4]; ++ grub_efi_uint8_t bootp_si_addr[4]; ++ grub_efi_uint8_t bootp_gi_addr[4]; ++ grub_efi_uint8_t bootp_hw_addr[16]; ++ grub_efi_uint8_t bootp_srv_name[64]; ++ grub_efi_uint8_t bootp_boot_file[128]; ++ grub_efi_uint32_t dhcp_magik; ++ grub_efi_uint8_t dhcp_options[56]; ++} grub_efi_pxe_dhcpv4_packet_t; ++ ++struct grub_efi_pxe_dhcpv6_packet ++{ ++ grub_efi_uint32_t message_type:8; ++ grub_efi_uint32_t transaction_id:24; ++ grub_efi_uint8_t dhcp_options[1024]; ++} GRUB_PACKED; ++typedef struct grub_efi_pxe_dhcpv6_packet grub_efi_pxe_dhcpv6_packet_t; ++ ++typedef union ++{ ++ grub_efi_uint8_t raw[1472]; ++ grub_efi_pxe_dhcpv4_packet_t dhcpv4; ++ grub_efi_pxe_dhcpv6_packet_t dhcpv6; ++} grub_efi_pxe_packet_t; ++ ++#define GRUB_EFI_PXE_MAX_IPCNT 8 ++#define GRUB_EFI_PXE_MAX_ARP_ENTRIES 8 ++#define GRUB_EFI_PXE_MAX_ROUTE_ENTRIES 8 ++ ++typedef struct grub_efi_pxe_ip_filter ++{ ++ grub_efi_uint8_t filters; ++ grub_efi_uint8_t ip_count; ++ grub_efi_uint8_t reserved; ++ grub_efi_ip_address_t ip_list[GRUB_EFI_PXE_MAX_IPCNT]; ++} grub_efi_pxe_ip_filter_t; ++ ++typedef struct grub_efi_pxe_arp_entry ++{ ++ grub_efi_ip_address_t ip_addr; ++ grub_efi_mac_address_t mac_addr; ++} grub_efi_pxe_arp_entry_t; ++ ++typedef struct grub_efi_pxe_route_entry ++{ ++ grub_efi_ip_address_t ip_addr; ++ grub_efi_ip_address_t subnet_mask; ++ grub_efi_ip_address_t gateway_addr; ++} grub_efi_pxe_route_entry_t; ++ ++typedef struct grub_efi_pxe_icmp_error ++{ ++ grub_efi_uint8_t type; ++ grub_efi_uint8_t code; ++ grub_efi_uint16_t checksum; ++ union ++ { ++ grub_efi_uint32_t reserved; ++ grub_efi_uint32_t mtu; ++ grub_efi_uint32_t pointer; ++ struct ++ { ++ grub_efi_uint16_t identifier; ++ grub_efi_uint16_t sequence; ++ } echo; ++ } u; ++ grub_efi_uint8_t data[494]; ++} grub_efi_pxe_icmp_error_t; ++ ++typedef struct grub_efi_pxe_tftp_error ++{ ++ grub_efi_uint8_t error_code; ++ grub_efi_char8_t error_string[127]; ++} grub_efi_pxe_tftp_error_t; + + typedef struct grub_efi_pxe_mode + { +- grub_uint8_t unused[52]; ++ grub_efi_boolean_t started; ++ grub_efi_boolean_t ipv6_available; ++ grub_efi_boolean_t ipv6_supported; ++ grub_efi_boolean_t using_ipv6; ++ grub_efi_boolean_t bis_supported; ++ grub_efi_boolean_t bis_detected; ++ grub_efi_boolean_t auto_arp; ++ grub_efi_boolean_t send_guid; ++ grub_efi_boolean_t dhcp_discover_valid; ++ grub_efi_boolean_t dhcp_ack_received; ++ grub_efi_boolean_t proxy_offer_received; ++ grub_efi_boolean_t pxe_discover_valid; ++ grub_efi_boolean_t pxe_reply_received; ++ grub_efi_boolean_t pxe_bis_reply_received; ++ grub_efi_boolean_t icmp_error_received; ++ grub_efi_boolean_t tftp_error_received; ++ grub_efi_boolean_t make_callbacks; ++ grub_efi_uint8_t ttl; ++ grub_efi_uint8_t tos; ++ grub_efi_ip_address_t station_ip; ++ grub_efi_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_efi_uint32_t arp_cache_entries; ++ grub_efi_pxe_arp_entry_t arp_cache[GRUB_EFI_PXE_MAX_ARP_ENTRIES]; ++ grub_efi_uint32_t route_table_entries; ++ grub_efi_pxe_route_entry_t route_table[GRUB_EFI_PXE_MAX_ROUTE_ENTRIES]; ++ grub_efi_pxe_icmp_error_t icmp_error; ++ grub_efi_pxe_tftp_error_t tftp_error; + } grub_efi_pxe_mode_t; + + typedef struct grub_efi_pxe +diff --git a/include/grub/net.h b/include/grub/net.h +index 88fc71ceffe..c7b8e2ac885 100644 +--- a/include/grub/net.h ++++ b/include/grub/net.h +@@ -418,6 +418,51 @@ struct grub_net_bootp_packet + grub_uint8_t vendor[0]; + } GRUB_PACKED; + ++enum ++ { ++ GRUB_NET_DHCP6_IA_NA = 3, ++ GRUB_NET_DHCP6_IA_ADDRESS = 5, ++ GRUB_NET_DHCP6_BOOTFILE_URL = 59, ++ }; ++ ++struct grub_net_dhcpv6_option ++{ ++ grub_uint16_t option_num; ++ grub_uint16_t option_len; ++ grub_uint8_t option_data[]; ++} GRUB_PACKED; ++typedef struct grub_net_dhcpv6_option grub_net_dhcpv6_option_t; ++ ++struct grub_net_dhcpv6_opt_ia_na ++{ ++ grub_uint16_t option_num; ++ grub_uint16_t option_len; ++ grub_uint32_t iaid; ++ grub_uint32_t t1; ++ grub_uint32_t t2; ++ grub_uint8_t options[]; ++} GRUB_PACKED; ++typedef struct grub_net_dhcpv6_opt_ia_na grub_net_dhcpv6_opt_ia_na_t; ++ ++struct grub_net_dhcpv6_opt_ia_address ++{ ++ grub_uint16_t option_num; ++ grub_uint16_t option_len; ++ grub_uint64_t ipv6_address[2]; ++ grub_uint32_t preferred_lifetime; ++ grub_uint32_t valid_lifetime; ++ grub_uint8_t options[]; ++} GRUB_PACKED; ++typedef struct grub_net_dhcpv6_opt_ia_address grub_net_dhcpv6_opt_ia_address_t; ++ ++struct grub_net_dhcpv6_packet ++{ ++ grub_uint32_t message_type:8; ++ grub_uint32_t transaction_id:24; ++ grub_uint8_t dhcp_options[1024]; ++} GRUB_PACKED; ++typedef struct grub_net_dhcpv6_packet grub_net_dhcpv6_packet_t; ++ + #define GRUB_NET_BOOTP_RFC1048_MAGIC_0 0x63 + #define GRUB_NET_BOOTP_RFC1048_MAGIC_1 0x82 + #define GRUB_NET_BOOTP_RFC1048_MAGIC_2 0x53 +@@ -446,6 +491,21 @@ grub_net_configure_by_dhcp_ack (const char *name, + grub_size_t size, + int is_def, char **device, char **path); + ++struct grub_net_network_level_interface * ++grub_net_configure_by_dhcpv6_ack (const char *name, ++ struct grub_net_card *card, ++ grub_net_interface_flags_t flags, ++ const grub_net_link_level_address_t *hwaddr, ++ const struct grub_net_dhcpv6_packet *packet, ++ int is_def, char **device, char **path); ++ ++int ++grub_ipv6_get_masksize(grub_uint8_t *mask); ++ ++grub_err_t ++grub_net_add_ipv6_local (struct grub_net_network_level_interface *inf, ++ int mask); ++ + grub_err_t + grub_net_add_ipv4_local (struct grub_net_network_level_interface *inf, + int mask); diff --git a/SOURCES/0201-ppc64le-has-no-separate-boot-mount-1261926.patch b/SOURCES/0201-ppc64le-has-no-separate-boot-mount-1261926.patch new file mode 100644 index 0000000..10cf282 --- /dev/null +++ b/SOURCES/0201-ppc64le-has-no-separate-boot-mount-1261926.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robert Marshall +Date: Fri, 17 Jun 2016 11:47:34 -0400 +Subject: [PATCH] ppc64le has no separate /boot mount (#1261926) + +The patch for rhbz#1212114 ensures that ppc64le systems sync grub config +changes to disk prior to grub-mkconfig completion and a reboot. + +This patch required checking for /boot as its own mount point because +issuing fsfreeze to a root partition is unwise. For administrators who +configured a ppc64le system with no separate /boot partition, the failed +check results in an error message. The file is written and would work +most of the time, however, it also introduces a corner case where the +behavior manifested in rhbz#1212114 could re-appear on these systems. + +The system call issued by fsfreeeze is being issued by methods within +the anaconda installer and can be removed from GRUB proper. + +Related: rhbz#1315468 +Resolves: rhbz#1261926 +--- + util/grub-mkconfig.in | 9 --------- + 1 file changed, 9 deletions(-) + +diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in +index 7db89499949..0cfe6047539 100644 +--- a/util/grub-mkconfig.in ++++ b/util/grub-mkconfig.in +@@ -291,12 +291,3 @@ fi + + gettext "done" >&2 + echo >&2 +- +-# make sure changes make it to the disk. +-# if /boot is a mountpoint, force the meta data on disk +-# to by-pass writeback delay. +-# PPC64LE-only to deal with Petitboot issues +-ARCH=$(uname -m) +-if [ "${ARCH}" = "ppc64le" ]; then +- sync && mountpoint -q /boot &&fsfreeze -f /boot && fsfreeze -u /boot +-fi diff --git a/SOURCES/0202-Add-grub-get-kernel-settings-and-use-it-in-10_linux.patch b/SOURCES/0202-Add-grub-get-kernel-settings-and-use-it-in-10_linux.patch new file mode 100644 index 0000000..b9c7b05 --- /dev/null +++ b/SOURCES/0202-Add-grub-get-kernel-settings-and-use-it-in-10_linux.patch @@ -0,0 +1,312 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 23 Jun 2016 11:01:39 -0400 +Subject: [PATCH] Add grub-get-kernel-settings and use it in 10_linux + +This patch adds grub-get-kernel-settings, which reads the system kernel +installation configuration from /etc/sysconfig/kernel, and outputs +${GRUB_...} variables suitable for evaluation by grub-mkconfig. Those +variables are then used by 10_linux to choose whether or not to create +debug stanzas. + +Resolves: rhbz#1226325 +--- + configure.ac | 2 + + Makefile.util.def | 7 ++ + .gitignore | 1 + + util/bash-completion.d/grub-completion.bash.in | 22 +++++++ + util/grub-get-kernel-settings.3 | 20 ++++++ + util/grub-get-kernel-settings.in | 91 ++++++++++++++++++++++++++ + util/grub-mkconfig.in | 3 + + util/grub.d/10_linux.in | 23 +++++-- + 8 files changed, 164 insertions(+), 5 deletions(-) + create mode 100644 util/grub-get-kernel-settings.3 + create mode 100644 util/grub-get-kernel-settings.in + +diff --git a/configure.ac b/configure.ac +index 04c052dc610..8b10a93cb56 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -58,6 +58,7 @@ grub_TRANSFORM([grub-install]) + grub_TRANSFORM([grub-mkconfig]) + grub_TRANSFORM([grub-mkfont]) + grub_TRANSFORM([grub-mkimage]) ++grub_TRANSFORM([grub-get-kernel-settings]) + grub_TRANSFORM([grub-glue-efi]) + grub_TRANSFORM([grub-mklayout]) + grub_TRANSFORM([grub-mkpasswd-pbkdf2]) +@@ -75,6 +76,7 @@ grub_TRANSFORM([grub-file]) + grub_TRANSFORM([grub-bios-setup.3]) + grub_TRANSFORM([grub-editenv.1]) + grub_TRANSFORM([grub-fstest.3]) ++grub_TRANSFORM([grub-get-kernel-settings.3]) + grub_TRANSFORM([grub-glue-efi.3]) + grub_TRANSFORM([grub-install.1]) + grub_TRANSFORM([grub-kbdcomp.3]) +diff --git a/Makefile.util.def b/Makefile.util.def +index e2821a2f3a5..3918e3b5292 100644 +--- a/Makefile.util.def ++++ b/Makefile.util.def +@@ -704,6 +704,13 @@ script = { + installdir = sbin; + }; + ++script = { ++ name = grub-get-kernel-settings; ++ common = util/grub-get-kernel-settings.in; ++ mansection = 3; ++ installdir = sbin; ++}; ++ + script = { + name = grub-set-default; + common = util/grub-set-default.in; +diff --git a/.gitignore b/.gitignore +index e49f76b114a..547ef0bcff0 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -61,6 +61,7 @@ grub-fstest.exe + grub_fstest_init.c + grub_fstest_init.h + grub_func_test ++grub-get-kernel-settings + grub-install + grub-install.exe + grub-kbdcomp +diff --git a/util/bash-completion.d/grub-completion.bash.in b/util/bash-completion.d/grub-completion.bash.in +index 44bf135b9f8..5c4acd496d4 100644 +--- a/util/bash-completion.d/grub-completion.bash.in ++++ b/util/bash-completion.d/grub-completion.bash.in +@@ -264,6 +264,28 @@ have ${__grub_sparc64_setup_program} && \ + unset __grub_sparc64_setup_program + + ++# ++# grub-get-kernel-settings ++# ++_grub_get_kernel_settings () { ++ local cur ++ ++ COMPREPLY=() ++ cur=`_get_cword` ++ ++ if [[ "$cur" == -* ]]; then ++ __grubcomp "$(__grub_get_options_from_help)" ++ else ++ # Default complete with a filename ++ _filedir ++ fi ++} ++__grub_get_kernel_settings_program="@grub_get_kernel_settings@" ++have ${__grub_get_kernel_settings_program} && \ ++ complete -F _grub_get_kernel_settings -o filenames ${__grub_get_kernel_settings_program} ++unset __grub_get_kernel_settings_program ++ ++ + # + # grub-install + # +diff --git a/util/grub-get-kernel-settings.3 b/util/grub-get-kernel-settings.3 +new file mode 100644 +index 00000000000..ba33330e28d +--- /dev/null ++++ b/util/grub-get-kernel-settings.3 +@@ -0,0 +1,20 @@ ++.TH GRUB-GET-KERNEL-SETTINGS 3 "Thu Jun 25 2015" ++.SH NAME ++\fBgrub-get-kernel-settings\fR \(em Evaluate the system's kernel installation settings for use while making a grub configuration file. ++ ++.SH SYNOPSIS ++\fBgrub-get-kernel-settings\fR [OPTION] ++ ++.SH DESCRIPTION ++\fBgrub-get-kernel-settings\fR reads the kernel installation settings on the host system, and emits a set of grub settings suitable for use when creating a grub configuration file. ++ ++.SH OPTIONS ++.TP ++-h, --help ++Display program usage and exit. ++.TP ++-v, --version ++Display the current version. ++ ++.SH SEE ALSO ++.BR "info grub" +diff --git a/util/grub-get-kernel-settings.in b/util/grub-get-kernel-settings.in +new file mode 100644 +index 00000000000..ae0b4696d49 +--- /dev/null ++++ b/util/grub-get-kernel-settings.in +@@ -0,0 +1,91 @@ ++#!/bin/sh ++set -e ++ ++# Evaluate new-kernel-pkg's configuration file. ++# Copyright (C) 2016 Free Software Foundation, Inc. ++# ++# GRUB is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++# ++# GRUB is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with GRUB. If not, see . ++ ++prefix="@prefix@" ++exec_prefix="@exec_prefix@" ++datarootdir="@datarootdir@" ++ ++prefix="@prefix@" ++exec_prefix="@exec_prefix@" ++sbindir="@sbindir@" ++bindir="@bindir@" ++sysconfdir="@sysconfdir@" ++PACKAGE_NAME=@PACKAGE_NAME@ ++PACKAGE_VERSION=@PACKAGE_VERSION@ ++host_os=@host_os@ ++datadir="@datadir@" ++if [ "x$pkgdatadir" = x ]; then ++ pkgdatadir="${datadir}/@PACKAGE@" ++fi ++grub_cfg="" ++ ++self=`basename $0` ++ ++grub_probe="${sbindir}/@grub_probe@" ++grub_file="${bindir}/@grub_file@" ++grub_editenv="${bindir}/@grub_editenv@" ++grub_script_check="${bindir}/@grub_script_check@" ++ ++export TEXTDOMAIN=@PACKAGE@ ++export TEXTDOMAINDIR="@localedir@" ++ ++. "${pkgdatadir}/grub-mkconfig_lib" ++ ++# Usage: usage ++# Print the usage. ++usage () { ++ gettext_printf "Usage: %s [OPTION]\n" "$self" ++ gettext "Evaluate new-kernel-pkg configuration"; echo ++ echo ++ print_option_help "-h, --help" "$(gettext "print this message and exit")" ++ print_option_help "-v, --version" "$(gettext "print the version information and exit")" ++ echo ++} ++ ++# Check the arguments. ++while test $# -gt 0 ++do ++ option=$1 ++ shift ++ ++ case "$option" in ++ -h | --help) ++ usage ++ exit 0 ;; ++ -v | --version) ++ echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" ++ exit 0 ;; ++ -*) ++ gettext_printf "Unrecognized option \`%s'\n" "$option" 1>&2 ++ usage ++ exit 1 ++ ;; ++ # Explicitly ignore non-option arguments, for compatibility. ++ esac ++done ++ ++if test -f /etc/sysconfig/kernel ; then ++ . /etc/sysconfig/kernel ++fi ++ ++if [ "$MAKEDEBUG" = "yes" ]; then ++ echo GRUB_LINUX_MAKE_DEBUG=true ++ echo GRUB_CMDLINE_LINUX_DEBUG=\"systemd.log_level=debug systemd.log_target=kmsg\" ++ echo GRUB_LINUX_DEBUG_TITLE_POSTFIX=\" with debugging\" ++fi +diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in +index 0cfe6047539..aa4fdb8a3b2 100644 +--- a/util/grub-mkconfig.in ++++ b/util/grub-mkconfig.in +@@ -42,6 +42,7 @@ grub_probe="${sbindir}/@grub_probe@" + grub_file="${bindir}/@grub_file@" + grub_editenv="${bindir}/@grub_editenv@" + grub_script_check="${bindir}/@grub_script_check@" ++grub_get_kernel_settings="${sbindir}/@grub_get_kernel_settings@" + + export TEXTDOMAIN=@PACKAGE@ + export TEXTDOMAINDIR="@localedir@" +@@ -148,6 +149,8 @@ if test -f ${sysconfdir}/default/grub ; then + . ${sysconfdir}/default/grub + fi + ++eval `${grub_get_kernel_settings}` || true ++ + if [ "x$GRUB_DISABLE_UUID" != "xtrue" -a -z "$GRUB_DEVICE_UUID" ]; then + GRUB_DEVICE_UUID="$GRUB_DEVICE_UUID_GENERATED" + fi +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index b3c460cb266..0d0086d3b6a 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -99,7 +99,8 @@ linux_entry () + os="$1" + version="$2" + type="$3" +- args="$4" ++ isdebug="$4" ++ args="$5" + + sixteenbit="" + linuxefi="linux" +@@ -130,6 +131,9 @@ linux_entry () + else + echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/" + fi ++ if [ x$isdebug = xdebug ]; then ++ title="$title${GRUB_LINUX_DEBUG_TITLE_POSTFIX}" ++ fi + if [ x$type != xrecovery ] ; then + save_default_entry | grub_add_tab + fi +@@ -281,11 +285,15 @@ while [ "x$list" != "x" ] ; do + fi + + if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xtrue ]; then +- linux_entry "${OS}" "${version}" simple \ ++ linux_entry "${OS}" "${version}" simple standard \ + "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" ++ if [ "x$GRUB_LINUX_MAKE_DEBUG" = "xtrue" ]; then ++ linux_entry "${OS}" "${version}" simple debug \ ++ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} ${GRUB_CMDLINE_LINUX_DEBUG}" ++ fi + + submenu_indentation="$grub_tab" +- ++ + if [ -z "$boot_device_id" ]; then + boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")" + fi +@@ -294,10 +302,15 @@ while [ "x$list" != "x" ] ; do + is_top_level=false + fi + +- linux_entry "${OS}" "${version}" advanced \ ++ linux_entry "${OS}" "${version}" advanced standard \ + "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" ++ if [ "x$GRUB_LINUX_MAKE_DEBUG" = "xtrue" ]; then ++ linux_entry "${OS}" "${version}" advanced debug \ ++ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} ${GRUB_CMDLINE_LINUX_DEBUG}" ++ fi ++ + if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then +- linux_entry "${OS}" "${version}" recovery \ ++ linux_entry "${OS}" "${version}" recovery standard \ + "single ${GRUB_CMDLINE_LINUX}" + fi + diff --git a/SOURCES/0203-Fix-coverity-issues-in-shell-scripts-1226325.patch b/SOURCES/0203-Fix-coverity-issues-in-shell-scripts-1226325.patch new file mode 100644 index 0000000..7ebed51 --- /dev/null +++ b/SOURCES/0203-Fix-coverity-issues-in-shell-scripts-1226325.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robert Marshall +Date: Thu, 7 Jul 2016 15:05:26 -0400 +Subject: [PATCH] Fix coverity issues in shell scripts (#1226325) + +Remove unused variables called out by coverity. Convert a non-quoted +variable to a quoted variable without use of deprecated backticks. + +Related: rhbz#1226325 +--- + util/grub-get-kernel-settings.in | 9 --------- + util/grub-mkconfig.in | 2 +- + 2 files changed, 1 insertion(+), 10 deletions(-) + +diff --git a/util/grub-get-kernel-settings.in b/util/grub-get-kernel-settings.in +index ae0b4696d49..cee8c209650 100644 +--- a/util/grub-get-kernel-settings.in ++++ b/util/grub-get-kernel-settings.in +@@ -21,27 +21,18 @@ prefix="@prefix@" + exec_prefix="@exec_prefix@" + datarootdir="@datarootdir@" + +-prefix="@prefix@" + exec_prefix="@exec_prefix@" + sbindir="@sbindir@" + bindir="@bindir@" +-sysconfdir="@sysconfdir@" + PACKAGE_NAME=@PACKAGE_NAME@ + PACKAGE_VERSION=@PACKAGE_VERSION@ +-host_os=@host_os@ + datadir="@datadir@" + if [ "x$pkgdatadir" = x ]; then + pkgdatadir="${datadir}/@PACKAGE@" + fi +-grub_cfg="" + + self=`basename $0` + +-grub_probe="${sbindir}/@grub_probe@" +-grub_file="${bindir}/@grub_file@" +-grub_editenv="${bindir}/@grub_editenv@" +-grub_script_check="${bindir}/@grub_script_check@" +- + export TEXTDOMAIN=@PACKAGE@ + export TEXTDOMAINDIR="@localedir@" + +diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in +index aa4fdb8a3b2..86801aa4e5c 100644 +--- a/util/grub-mkconfig.in ++++ b/util/grub-mkconfig.in +@@ -149,7 +149,7 @@ if test -f ${sysconfdir}/default/grub ; then + . ${sysconfdir}/default/grub + fi + +-eval `${grub_get_kernel_settings}` || true ++eval "$("${grub_get_kernel_settings}")" || true + + if [ "x$GRUB_DISABLE_UUID" != "xtrue" -a -z "$GRUB_DEVICE_UUID" ]; then + GRUB_DEVICE_UUID="$GRUB_DEVICE_UUID_GENERATED" diff --git a/SOURCES/0204-Fix-compiler-warning-1154226.patch b/SOURCES/0204-Fix-compiler-warning-1154226.patch new file mode 100644 index 0000000..bbc07f5 --- /dev/null +++ b/SOURCES/0204-Fix-compiler-warning-1154226.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robert Marshall +Date: Thu, 7 Jul 2016 16:30:32 -0400 +Subject: [PATCH] Fix compiler warning (#1154226) + +Coverity threw a compiler warning for an incompatible pointer type when +referencing a union. Converted the argument to pass the exact member of the +union instead of just the union itself. + +Related: rhbz#1154226 +--- + grub-core/net/drivers/efi/efinet.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index d7befb2ba9b..ed103df7a80 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -415,7 +415,7 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + sizeof (hwaddr.mac)); + + grub_net_configure_by_dhcpv6_ack (card->name, card, 0, +- &hwaddr, &pxe_mode->dhcp_ack, ++ &hwaddr, &pxe_mode->dhcp_ack.dhcpv6, + 1, device, path); + grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path); + } diff --git a/SOURCES/0205-Fix-CLANG-error-from-Coverity-1154226.patch b/SOURCES/0205-Fix-CLANG-error-from-Coverity-1154226.patch new file mode 100644 index 0000000..9144313 --- /dev/null +++ b/SOURCES/0205-Fix-CLANG-error-from-Coverity-1154226.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robert Marshall +Date: Mon, 11 Jul 2016 10:59:48 -0400 +Subject: [PATCH] Fix CLANG error from Coverity (#1154226) + +Resolved a null pointer deference warning from coverity. + +Related: rhbz#1154226 +--- + grub-core/net/url.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/grub-core/net/url.c b/grub-core/net/url.c +index 537019f2c78..146858284cd 100644 +--- a/grub-core/net/url.c ++++ b/grub-core/net/url.c +@@ -267,7 +267,12 @@ extract_http_url_info (char *url, int ssl, + } + + l = host_end - host_off; +- c = *host_end; ++ ++ if (host_end == NULL) ++ goto fail; ++ else ++ c = *host_end; ++ + *host_end = '\0'; + *host = grub_strndup (host_off, l); + *host_end = c; diff --git a/SOURCES/0206-grub_ipv6_get_masksize-fix-loop-iteration-error.patch b/SOURCES/0206-grub_ipv6_get_masksize-fix-loop-iteration-error.patch new file mode 100644 index 0000000..9220c3d --- /dev/null +++ b/SOURCES/0206-grub_ipv6_get_masksize-fix-loop-iteration-error.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 11 Jul 2016 15:43:01 -0400 +Subject: [PATCH] grub_ipv6_get_masksize: fix loop iteration error + +Related: rhbz#1154226 + +Signed-off-by: Peter Jones +--- + grub-core/net/net.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/net/net.c b/grub-core/net/net.c +index 81d3b6208cb..19a81bc9e78 100644 +--- a/grub-core/net/net.c ++++ b/grub-core/net/net.c +@@ -983,7 +983,7 @@ grub_ipv6_get_masksize(grub_uint8_t *be_mask) + + mask = (grub_uint8_t *)mask16; + +- for (x = 15; x > 0; x++) ++ for (x = 15; x > 0; x--) + { + grub_uint8_t octet = mask[x]; + while (octet & 0x80) diff --git a/SOURCES/0207-efinet-fix-some-coverity-gripes.patch b/SOURCES/0207-efinet-fix-some-coverity-gripes.patch new file mode 100644 index 0000000..170cb6a --- /dev/null +++ b/SOURCES/0207-efinet-fix-some-coverity-gripes.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 11 Jul 2016 15:57:28 -0400 +Subject: [PATCH] efinet: fix some coverity gripes. + +Related: rhbz#1154226 + +Signed-off-by: Peter Jones +--- + grub-core/net/bootp.c | 9 +++++---- + grub-core/net/drivers/efi/efinet.c | 11 +++++++---- + 2 files changed, 12 insertions(+), 8 deletions(-) + +diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c +index 4793ebc434e..46ce8135ac5 100644 +--- a/grub-core/net/bootp.c ++++ b/grub-core/net/bootp.c +@@ -349,10 +349,11 @@ grub_net_configure_by_dhcpv6_ack (const char *name, + struct grub_net_network_level_address addr; + int mask = -1; + +- if (device) +- *device = 0; +- if (path) +- *path = 0; ++ if (!device || !path) ++ return NULL; ++ ++ *device = 0; ++ *path = 0; + + grub_dprintf ("net", "mac address is %02x:%02x:%02x:%02x:%02x:%02x\n", + hwaddr->mac[0], hwaddr->mac[1], hwaddr->mac[2], +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index ed103df7a80..2244f14030f 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -401,6 +401,7 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + if (pxe_mode->using_ipv6) + { + grub_net_link_level_address_t hwaddr; ++ struct grub_net_network_level_interface *intf; + + grub_dprintf ("efinet", "using ipv6 and dhcpv6\n"); + grub_dprintf ("efinet", "dhcp_ack_received: %s%s\n", +@@ -414,10 +415,12 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + card->efi_net->mode->current_address, + sizeof (hwaddr.mac)); + +- grub_net_configure_by_dhcpv6_ack (card->name, card, 0, +- &hwaddr, &pxe_mode->dhcp_ack.dhcpv6, +- 1, device, path); +- grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path); ++ intf = grub_net_configure_by_dhcpv6_ack (card->name, card, 0, ++ &hwaddr, ++ &pxe_mode->dhcp_ack.dhcpv6, ++ 1, device, path); ++ if (intf && device && path) ++ grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path); + } + else + { diff --git a/SOURCES/0208-Fix-another-coverity-gripe-about-a-missing-typecast.patch b/SOURCES/0208-Fix-another-coverity-gripe-about-a-missing-typecast.patch new file mode 100644 index 0000000..91f2f30 --- /dev/null +++ b/SOURCES/0208-Fix-another-coverity-gripe-about-a-missing-typecast.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 12 Jul 2016 10:23:42 -0400 +Subject: [PATCH] Fix another coverity gripe about a missing typecast. + +Related: rhbz#1154226 + +Signed-off-by: Peter Jones +--- + grub-core/net/drivers/efi/efinet.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index 2244f14030f..69b0fc7a8fe 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -415,10 +415,9 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + card->efi_net->mode->current_address, + sizeof (hwaddr.mac)); + +- intf = grub_net_configure_by_dhcpv6_ack (card->name, card, 0, +- &hwaddr, +- &pxe_mode->dhcp_ack.dhcpv6, +- 1, device, path); ++ intf = grub_net_configure_by_dhcpv6_ack (card->name, card, 0, &hwaddr, ++ (const struct grub_net_dhcpv6_packet *)&pxe_mode->dhcp_ack.dhcpv6, ++ 1, device, path); + if (intf && device && path) + grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path); + } diff --git a/SOURCES/0209-Fix-duplicate-shell-entries-1226325.patch b/SOURCES/0209-Fix-duplicate-shell-entries-1226325.patch new file mode 100644 index 0000000..2b036af --- /dev/null +++ b/SOURCES/0209-Fix-duplicate-shell-entries-1226325.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Robert Marshall +Date: Tue, 12 Jul 2016 10:25:16 -0400 +Subject: [PATCH] Fix duplicate shell entries (#1226325) + +Coverity discovered more of the same non-used shell variables that had +appeared more than once in the file. + +Related: rhbz#1226325 +--- + util/grub-get-kernel-settings.in | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/util/grub-get-kernel-settings.in b/util/grub-get-kernel-settings.in +index cee8c209650..6a68a0ef664 100644 +--- a/util/grub-get-kernel-settings.in ++++ b/util/grub-get-kernel-settings.in +@@ -17,13 +17,6 @@ set -e + # You should have received a copy of the GNU General Public License + # along with GRUB. If not, see . + +-prefix="@prefix@" +-exec_prefix="@exec_prefix@" +-datarootdir="@datarootdir@" +- +-exec_prefix="@exec_prefix@" +-sbindir="@sbindir@" +-bindir="@bindir@" + PACKAGE_NAME=@PACKAGE_NAME@ + PACKAGE_VERSION=@PACKAGE_VERSION@ + datadir="@datadir@" diff --git a/SOURCES/0210-Coverity-rightly-noticed-that-grub_ipv6_get_masksize.patch b/SOURCES/0210-Coverity-rightly-noticed-that-grub_ipv6_get_masksize.patch new file mode 100644 index 0000000..5936422 --- /dev/null +++ b/SOURCES/0210-Coverity-rightly-noticed-that-grub_ipv6_get_masksize.patch @@ -0,0 +1,87 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 12 Jul 2016 11:59:39 -0400 +Subject: [PATCH] Coverity rightly noticed that grub_ipv6_get_masksize() was + broken. + +This fixes it with a version that even seems to work. + +Related: rhbz#1154226 + +Signed-off-by: Peter Jones +--- + grub-core/net/net.c | 27 ++++++++++++++++----------- + include/grub/net.h | 2 +- + 2 files changed, 17 insertions(+), 12 deletions(-) + +diff --git a/grub-core/net/net.c b/grub-core/net/net.c +index 19a81bc9e78..36fc0d8b2e8 100644 +--- a/grub-core/net/net.c ++++ b/grub-core/net/net.c +@@ -970,29 +970,34 @@ grub_net_network_level_interface_register (struct grub_net_network_level_interfa + } + + int +-grub_ipv6_get_masksize(grub_uint8_t *be_mask) ++grub_ipv6_get_masksize (grub_uint16_t be_mask[8]) + { + grub_uint8_t *mask; + grub_uint16_t mask16[8]; +- unsigned int x; +- int ret = 0; ++ int x, y; ++ int ret = 128; + +- grub_memcpy (mask16, be_mask, sizeof(mask16)); ++ grub_memcpy (mask16, be_mask, sizeof (mask16)); + for (x = 0; x < 8; x++) + mask16[x] = grub_be_to_cpu16 (mask16[x]); + + mask = (grub_uint8_t *)mask16; + +- for (x = 15; x > 0; x--) ++ for (x = 15; x >= 0; x--) + { + grub_uint8_t octet = mask[x]; +- while (octet & 0x80) ++ if (!octet) + { +- ret++; +- octet <<= 1; ++ ret -= 8; ++ continue; ++ } ++ for (y = 0; y < 8; y++) ++ { ++ if (octet & (1 << y)) ++ break; ++ else ++ ret--; + } +- if (ret) +- ret += 8 * (15 - x); + break; + } + +@@ -1009,7 +1014,7 @@ grub_net_add_ipv6_local (struct grub_net_network_level_interface *inter, + return 0; + + if (mask == -1) +- mask = grub_ipv6_get_masksize ((grub_uint8_t *)inter->address.ipv6); ++ mask = grub_ipv6_get_masksize ((grub_uint16_t *)inter->address.ipv6); + + if (mask == -1) + return 0; +diff --git a/include/grub/net.h b/include/grub/net.h +index c7b8e2ac885..bd930f4dd8c 100644 +--- a/include/grub/net.h ++++ b/include/grub/net.h +@@ -500,7 +500,7 @@ grub_net_configure_by_dhcpv6_ack (const char *name, + int is_def, char **device, char **path); + + int +-grub_ipv6_get_masksize(grub_uint8_t *mask); ++grub_ipv6_get_masksize(grub_uint16_t *mask); + + grub_err_t + grub_net_add_ipv6_local (struct grub_net_network_level_interface *inf, diff --git a/SOURCES/0211-Export-grub-get-kernel-settings-variables.patch b/SOURCES/0211-Export-grub-get-kernel-settings-variables.patch new file mode 100644 index 0000000..a2420d7 --- /dev/null +++ b/SOURCES/0211-Export-grub-get-kernel-settings-variables.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 25 Aug 2016 14:15:29 -0400 +Subject: [PATCH] Export grub-get-kernel-settings variables + +Without this export, the generators for various configs never get the +setting. + +Related: rhbz#1226325 + +Signed-off-by: Peter Jones +--- + util/grub-get-kernel-settings.in | 3 +++ + util/grub.d/10_linux.in | 6 +++--- + 2 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/util/grub-get-kernel-settings.in b/util/grub-get-kernel-settings.in +index 6a68a0ef664..12046219878 100644 +--- a/util/grub-get-kernel-settings.in ++++ b/util/grub-get-kernel-settings.in +@@ -70,6 +70,9 @@ fi + + if [ "$MAKEDEBUG" = "yes" ]; then + echo GRUB_LINUX_MAKE_DEBUG=true ++ echo export GRUB_LINUX_MAKE_DEBUG + echo GRUB_CMDLINE_LINUX_DEBUG=\"systemd.log_level=debug systemd.log_target=kmsg\" ++ echo export GRUB_CMDLINE_LINUX_DEBUG + echo GRUB_LINUX_DEBUG_TITLE_POSTFIX=\" with debugging\" ++ echo export GRUB_LINUX_DEBUG_TITLE_POSTFIX + fi +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index 0d0086d3b6a..bf0fb727bcd 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -127,13 +127,13 @@ linux_entry () + quoted="$(echo "$GRUB_ACTUAL_DEFAULT" | grub_quote)" + title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;" + fi ++ if [ x$isdebug = xdebug ]; then ++ title="$title${GRUB_LINUX_DEBUG_TITLE_POSTFIX}" ++ fi + echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' {" | sed "s/^/$submenu_indentation/" + else + echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/" + fi +- if [ x$isdebug = xdebug ]; then +- title="$title${GRUB_LINUX_DEBUG_TITLE_POSTFIX}" +- fi + if [ x$type != xrecovery ] ; then + save_default_entry | grub_add_tab + fi diff --git a/SOURCES/0212-Normalize-slashes-in-tftp-paths.patch b/SOURCES/0212-Normalize-slashes-in-tftp-paths.patch new file mode 100644 index 0000000..b89abf9 --- /dev/null +++ b/SOURCES/0212-Normalize-slashes-in-tftp-paths.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lenny Szubowicz +Date: Mon, 29 Aug 2016 11:04:48 -0400 +Subject: [PATCH] Normalize slashes in tftp paths. + +Some tftp servers do not handle multiple consecutive slashes correctly; +this patch avoids sending tftp requests with non-normalized paths. + +Signed-off-by: Peter Jones +--- + grub-core/net/tftp.c | 28 +++++++++++++++++++++++++--- + 1 file changed, 25 insertions(+), 3 deletions(-) + +diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c +index 22a4debdcd4..8632339de97 100644 +--- a/grub-core/net/tftp.c ++++ b/grub-core/net/tftp.c +@@ -300,6 +300,25 @@ destroy_pq (tftp_data_t data) + grub_priority_queue_destroy (data->pq); + } + ++/* Create a normalized copy of the filename. ++ Compress any string of consecutive forward slashes to a single forward ++ slash. */ ++static void ++grub_normalize_filename (char *normalized, const char *filename) ++{ ++ char *dest = normalized; ++ char *src = filename; ++ ++ while (*src != '\0') ++ { ++ if (src[0] == '/' && src[1] == '/') ++ src++; ++ else ++ *dest++ = *src++; ++ } ++ *dest = '\0'; ++} ++ + static grub_err_t + tftp_open (struct grub_file *file, const char *filename) + { +@@ -334,9 +353,12 @@ tftp_open (struct grub_file *file, const char *filename) + rrqlen = 0; + + tftph->opcode = grub_cpu_to_be16 (TFTP_RRQ); +- grub_strcpy (rrq, filename); +- rrqlen += grub_strlen (filename) + 1; +- rrq += grub_strlen (filename) + 1; ++ ++ /* Copy and normalize the filename to work-around issues on some tftp ++ servers when file names are being matched for remapping. */ ++ grub_normalize_filename (rrq, filename); ++ rrqlen += grub_strlen (rrq) + 1; ++ rrq += grub_strlen (rrq) + 1; + + grub_strcpy (rrq, "octet"); + rrqlen += grub_strlen ("octet") + 1; diff --git a/SOURCES/0213-bz1374141-fix-incorrect-mask-for-ppc64.patch b/SOURCES/0213-bz1374141-fix-incorrect-mask-for-ppc64.patch new file mode 100644 index 0000000..a0b1016 --- /dev/null +++ b/SOURCES/0213-bz1374141-fix-incorrect-mask-for-ppc64.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Masahiro Matsuya +Date: Sat, 29 Oct 2016 08:35:26 +0900 +Subject: [PATCH] bz1374141 fix incorrect mask for ppc64 + +The netmask configured in firmware is not respected on ppc64 (big endian). +When 255.255.252.0 is set as netmask in firmware, the following is the value of bootpath string in grub_ieee1275_parse_bootpath(). + + /vdevice/l-lan@30000002:speed=auto,duplex=auto,192.168.88.10,,192.168.89.113,192.168.88.1,5,5,255.255.252.0,512 + +The netmask in this bootpath is no problem, since it's a value specified in firmware. But, +The value of 'subnet_mask.ipv4' was set with 0xfffffc00, and __builtin_ctz (~grub_le_to_cpu32 (subnet_mask.ipv4)) returned 16 (not 22). +As a result, 16 was used for netmask wrongly. + +1111 1111 1111 1111 1111 1100 0000 0000 # subnet_mask.ipv4 (=0xfffffc00) +0000 0000 1111 1100 1111 1111 1111 1111 # grub_le_to_cpu32 (subnet_mask.ipv4) +1111 1111 0000 0011 0000 0000 0000 0000 # ~grub_le_to_cpu32 (subnet_mask.ipv4) + +And, the count of zero with __builtin_ctz can be 16. +This patch changes it as below. + +1111 1111 1111 1111 1111 1100 0000 0000 # subnet_mask.ipv4 (=0xfffffc00) +0000 0000 1111 1100 1111 1111 1111 1111 # grub_le_to_cpu32 (subnet_mask.ipv4) +1111 1111 1111 1111 1111 1100 0000 0000 # grub_swap_bytes32(grub_le_to_cpu32 (subnet_mask.ipv4)) +0000 0000 0000 0000 0000 0011 1111 1111 # ~grub_swap_bytes32(grub_le_to_cpu32 (subnet_mask.ipv4)) + +The count of zero with __builtin_clz can be 22. (clz counts the number of one bits preceding the most significant zero bit) +--- + grub-core/net/drivers/ieee1275/ofnet.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c +index eea8e71d300..cd24ddc99c5 100644 +--- a/grub-core/net/drivers/ieee1275/ofnet.c ++++ b/grub-core/net/drivers/ieee1275/ofnet.c +@@ -208,7 +208,7 @@ grub_ieee1275_parse_bootpath (const char *devpath, char *bootpath, + inter = grub_net_add_addr ((*card)->name, *card, &client_addr, &hw_addr, + flags); + grub_net_add_ipv4_local (inter, +- __builtin_ctz (~grub_le_to_cpu32 (subnet_mask.ipv4))); ++ __builtin_clz (~grub_swap_bytes32(grub_le_to_cpu32 (subnet_mask.ipv4)))); + } + + if (gateway_addr.ipv4 != 0) diff --git a/SOURCES/0214-Make-efi-machines-load-an-env-block-from-a-variable.patch b/SOURCES/0214-Make-efi-machines-load-an-env-block-from-a-variable.patch new file mode 100644 index 0000000..9f253ca --- /dev/null +++ b/SOURCES/0214-Make-efi-machines-load-an-env-block-from-a-variable.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 7 Dec 2015 14:20:49 -0500 +Subject: [PATCH] Make efi machines load an env block from a variable + +Signed-off-by: Peter Jones +--- + grub-core/Makefile.core.def | 1 + + grub-core/kern/efi/init.c | 34 +++++++++++++++++++++++++++++++++- + 2 files changed, 34 insertions(+), 1 deletion(-) + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index d73ea6f6c51..4fc74393335 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -173,6 +173,7 @@ kernel = { + efi = kern/efi/init.c; + efi = kern/efi/mm.c; + efi = term/efi/console.c; ++ efi = lib/envblk.c; + + x86 = kern/i386/tsc.c; + +diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c +index c391df48236..c5d8a76144a 100644 +--- a/grub-core/kern/efi/init.c ++++ b/grub-core/kern/efi/init.c +@@ -25,9 +25,40 @@ + #include + #include + #include ++#include + + grub_addr_t grub_modbase; + ++#define GRUB_EFI_GRUB_VARIABLE_GUID \ ++ { 0x91376aff, 0xcba6, 0x42be, \ ++ { 0x94, 0x9d, 0x06, 0xfd, 0xe8, 0x11, 0x28, 0xe8 } \ ++ } ++ ++/* Helper for grub_efi_env_init */ ++static int ++set_var (const char *name, const char *value, ++ void *whitelist __attribute__((__unused__))) ++{ ++ grub_env_set (name, value); ++ return 0; ++} ++ ++static void ++grub_efi_env_init (void) ++{ ++ grub_efi_guid_t efi_grub_guid = GRUB_EFI_GRUB_VARIABLE_GUID; ++ struct grub_envblk envblk_s = { NULL, 0 }; ++ grub_envblk_t envblk = &envblk_s; ++ ++ envblk_s.buf = grub_efi_get_variable ("GRUB_ENV", &efi_grub_guid, ++ &envblk_s.size); ++ if (!envblk_s.buf || envblk_s.size < 1) ++ return; ++ ++ grub_envblk_iterate (envblk, NULL, set_var); ++ grub_free (envblk_s.buf); ++} ++ + void + grub_efi_init (void) + { +@@ -42,10 +73,11 @@ grub_efi_init (void) + efi_call_4 (grub_efi_system_table->boot_services->set_watchdog_timer, + 0, 0, 0, NULL); + ++ grub_efi_env_init (); + grub_efidisk_init (); + } + +-void (*grub_efi_net_config) (grub_efi_handle_t hnd, ++void (*grub_efi_net_config) (grub_efi_handle_t hnd, + char **device, + char **path); + diff --git a/SOURCES/0215-Fix-race-in-EFI-validation.patch b/SOURCES/0215-Fix-race-in-EFI-validation.patch new file mode 100644 index 0000000..ce42a83 --- /dev/null +++ b/SOURCES/0215-Fix-race-in-EFI-validation.patch @@ -0,0 +1,94 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Tue, 14 Jul 2015 16:58:51 -0700 +Subject: [PATCH] Fix race in EFI validation + +--- + grub-core/loader/i386/efi/linux.c | 44 ++++++++++----------------------------- + 1 file changed, 11 insertions(+), 33 deletions(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index e5b778577f9..7ccf32d9d45 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -154,7 +154,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_file_t file = 0; + struct linux_kernel_header lh; + grub_ssize_t len, start, filelen; +- void *kernel; ++ void *kernel = NULL; + + grub_dl_ref (my_mod); + +@@ -191,10 +191,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + +- grub_file_seek (file, 0); +- +- grub_free(kernel); +- + params = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(16384)); + + if (! params) +@@ -203,15 +199,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + +- memset (params, 0, 16384); ++ grub_memset (params, 0, 16384); + +- if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) +- { +- if (!grub_errno) +- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), +- argv[0]); +- goto fail; +- } ++ grub_memcpy (&lh, kernel, sizeof (lh)); + + if (lh.boot_flag != grub_cpu_to_le16 (0xaa55)) + { +@@ -271,27 +261,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + +- if (grub_file_seek (file, start) == (grub_off_t) -1) +- { +- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), +- argv[0]); +- goto fail; +- } ++ grub_memcpy (kernel_mem, (char *)kernel + start, len); ++ grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0); ++ loaded=1; + +- if (grub_file_read (file, kernel_mem, len) != len && !grub_errno) +- { +- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), +- argv[0]); +- } +- +- if (grub_errno == GRUB_ERR_NONE) +- { +- grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0); +- loaded = 1; +- lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem; +- } +- +- memcpy(params, &lh, 2 * 512); ++ lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem; ++ grub_memcpy (params, &lh, 2 * 512); + + params->type_of_loader = 0x21; + +@@ -300,6 +275,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + if (file) + grub_file_close (file); + ++ if (kernel) ++ grub_free (kernel); ++ + if (grub_errno != GRUB_ERR_NONE) + { + grub_dl_unref (my_mod); diff --git a/SOURCES/0216-efi-chainloader-fix-use-after-free.patch b/SOURCES/0216-efi-chainloader-fix-use-after-free.patch new file mode 100644 index 0000000..6bbc6d5 --- /dev/null +++ b/SOURCES/0216-efi-chainloader-fix-use-after-free.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Sat, 20 Jun 2015 23:38:17 +0300 +Subject: [PATCH] efi/chainloader: fix use after free + +Found by: Coverity scan. +CID: 96714 +--- + grub-core/loader/efi/chainloader.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index 233237018b5..ec23cf4ed66 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -351,6 +351,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + loaded_image->device_handle = dev_handle; + + grub_file_close (file); ++ file = NULL; + + if (argc > 1) + { diff --git a/SOURCES/0217-chainloader-fix-resoource-leak.patch b/SOURCES/0217-chainloader-fix-resoource-leak.patch new file mode 100644 index 0000000..e078f02 --- /dev/null +++ b/SOURCES/0217-chainloader-fix-resoource-leak.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Fri, 26 Jun 2015 09:25:30 +0300 +Subject: [PATCH] chainloader: fix resoource leak + +Found by: Coverity scan. +CID: 96651 +--- + grub-core/loader/efi/chainloader.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index ec23cf4ed66..522a716e37d 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -350,9 +350,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + } + loaded_image->device_handle = dev_handle; + +- grub_file_close (file); +- file = NULL; +- + if (argc > 1) + { + int i, len; +@@ -382,6 +379,9 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + loaded_image->load_options_size = len; + } + ++ grub_file_close (file); ++ grub_device_close (dev); ++ + grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0); + return 0; + diff --git a/SOURCES/0218-efi-properly-terminate-filepath-with-NULL-in-chainlo.patch b/SOURCES/0218-efi-properly-terminate-filepath-with-NULL-in-chainlo.patch new file mode 100644 index 0000000..ff187f2 --- /dev/null +++ b/SOURCES/0218-efi-properly-terminate-filepath-with-NULL-in-chainlo.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Thu, 15 Dec 2016 16:07:00 +0300 +Subject: [PATCH] efi: properly terminate filepath with NULL in chainloader + +EFI File Path Media Device Path is defined as NULL terminated string; +but chainloader built file paths without final NULL. This caused error +with Secure Boot and Linux Foundation PreLoader on Acer with InsydeH20 BIOS. +Apparently firmware failed verification with EFI_INVALID_PARAMETER which is +considered fatal error by PreLoader. + +Reported and tested by Giovanni Santini +--- + grub-core/loader/efi/chainloader.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index 522a716e37d..adc85636633 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -122,6 +122,8 @@ copy_file_path (grub_efi_file_path_device_path_t *fp, + if (*p == '/') + *p = '\\'; + ++ /* File Path is NULL terminated */ ++ fp->path_name[size++] = '\0'; + fp->header.length = size * sizeof (grub_efi_char16_t) + sizeof (*fp); + } + +@@ -156,8 +158,10 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename) + d = GRUB_EFI_NEXT_DEVICE_PATH (d); + } + ++ /* File Path is NULL terminated. Allocate space for 2 extra characters */ ++ /* FIXME why we split path in two components? */ + file_path = grub_malloc (size +- + ((grub_strlen (dir_start) + 1) ++ + ((grub_strlen (dir_start) + 2) + * GRUB_MAX_UTF16_PER_UTF8 + * sizeof (grub_efi_char16_t)) + + sizeof (grub_efi_file_path_device_path_t) * 2); diff --git a/SOURCES/0219-Use-device-part-of-chainloader-target-if-present.patch b/SOURCES/0219-Use-device-part-of-chainloader-target-if-present.patch new file mode 100644 index 0000000..28efeb0 --- /dev/null +++ b/SOURCES/0219-Use-device-part-of-chainloader-target-if-present.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Raymund Will +Date: Fri, 10 Apr 2015 01:45:02 -0400 +Subject: [PATCH] Use device part of chainloader target, if present. + +Otherwise chainloading is restricted to '$root', which might not even +be readable by EFI! + +v1. use grub_file_get_device_name() to get device name + +Signed-off-by: Michael Chang +Signed-off-by: Peter Jones +--- + grub-core/loader/efi/chainloader.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index adc85636633..14ce6ddd7ad 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -223,8 +223,11 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + if (! file) + goto fail; + +- /* Get the root device's device path. */ +- dev = grub_device_open (0); ++ /* Get the device path from filename. */ ++ char *devname = grub_file_get_device_name (filename); ++ dev = grub_device_open (devname); ++ if (devname) ++ grub_free (devname); + if (! dev) + goto fail; + diff --git a/SOURCES/0220-Add-secureboot-support-on-efi-chainloader.patch b/SOURCES/0220-Add-secureboot-support-on-efi-chainloader.patch new file mode 100644 index 0000000..15f2968 --- /dev/null +++ b/SOURCES/0220-Add-secureboot-support-on-efi-chainloader.patch @@ -0,0 +1,797 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 6 Oct 2015 13:04:37 -0400 +Subject: [PATCH] Add secureboot support on efi chainloader + +Expand the chainloader to be able to verify the image by means of shim +lock protocol. The PE/COFF image is loaded and relocated by the +chainloader instead of calling LoadImage and StartImage UEFI boot +Service as they require positive verification result from keys enrolled +in KEK or DB. The shim will use MOK in addition to firmware enrolled +keys to verify the image. + +The chainloader module could be used to load other UEFI bootloaders, +such as xen.efi, and could be signed by any of MOK, KEK or DB. + +Based on https://build.opensuse.org/package/view_file/openSUSE:Factory/grub2/grub2-secureboot-chainloader.patch + +Signed-off-by: Peter Jones +--- + grub-core/loader/efi/chainloader.c | 612 ++++++++++++++++++++++++++++++++++--- + include/grub/efi/pe32.h | 20 +- + 2 files changed, 595 insertions(+), 37 deletions(-) + +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index 14ce6ddd7ad..87a91e16f17 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -32,6 +32,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -46,9 +48,14 @@ static grub_dl_t my_mod; + + static grub_efi_physical_address_t address; + static grub_efi_uintn_t pages; ++static grub_ssize_t fsize; + static grub_efi_device_path_t *file_path; + static grub_efi_handle_t image_handle; + static grub_efi_char16_t *cmdline; ++static grub_ssize_t cmdline_len; ++static grub_efi_handle_t dev_handle; ++ ++static grub_efi_status_t (*entry_point) (grub_efi_handle_t image_handle, grub_efi_system_table_t *system_table); + + static grub_err_t + grub_chainloader_unload (void) +@@ -63,6 +70,7 @@ grub_chainloader_unload (void) + grub_free (cmdline); + cmdline = 0; + file_path = 0; ++ dev_handle = 0; + + grub_dl_unref (my_mod); + return GRUB_ERR_NONE; +@@ -191,12 +199,523 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename) + return file_path; + } + ++#define SHIM_LOCK_GUID \ ++ { 0x605dab50, 0xe046, 0x4300, { 0xab,0xb6,0x3d,0xd8,0x10,0xdd,0x8b,0x23 } } ++ ++typedef union ++{ ++ struct grub_pe32_header_32 pe32; ++ struct grub_pe32_header_64 pe32plus; ++} grub_pe_header_t; ++ ++struct pe_coff_loader_image_context ++{ ++ grub_efi_uint64_t image_address; ++ grub_efi_uint64_t image_size; ++ grub_efi_uint64_t entry_point; ++ grub_efi_uintn_t size_of_headers; ++ grub_efi_uint16_t image_type; ++ grub_efi_uint16_t number_of_sections; ++ grub_efi_uint32_t section_alignment; ++ struct grub_pe32_section_table *first_section; ++ struct grub_pe32_data_directory *reloc_dir; ++ struct grub_pe32_data_directory *sec_dir; ++ grub_efi_uint64_t number_of_rva_and_sizes; ++ grub_pe_header_t *pe_hdr; ++}; ++ ++typedef struct pe_coff_loader_image_context pe_coff_loader_image_context_t; ++ ++struct grub_efi_shim_lock ++{ ++ grub_efi_status_t (*verify)(void *buffer, ++ grub_efi_uint32_t size); ++ grub_efi_status_t (*hash)(void *data, ++ grub_efi_int32_t datasize, ++ pe_coff_loader_image_context_t *context, ++ grub_efi_uint8_t *sha256hash, ++ grub_efi_uint8_t *sha1hash); ++ grub_efi_status_t (*context)(void *data, ++ grub_efi_uint32_t size, ++ pe_coff_loader_image_context_t *context); ++}; ++ ++typedef struct grub_efi_shim_lock grub_efi_shim_lock_t; ++ ++static grub_efi_boolean_t ++read_header (void *data, grub_efi_uint32_t size, ++ pe_coff_loader_image_context_t *context) ++{ ++ grub_efi_guid_t guid = SHIM_LOCK_GUID; ++ grub_efi_shim_lock_t *shim_lock; ++ grub_efi_status_t status; ++ ++ shim_lock = grub_efi_locate_protocol (&guid, NULL); ++ ++ if (!shim_lock) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "no shim lock protocol"); ++ return 0; ++ } ++ ++ status = shim_lock->context (data, size, context); ++ ++ if (status == GRUB_EFI_SUCCESS) ++ { ++ grub_dprintf ("chain", "context success\n"); ++ return 1; ++ } ++ ++ switch (status) ++ { ++ case GRUB_EFI_UNSUPPORTED: ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "context error unsupported"); ++ break; ++ case GRUB_EFI_INVALID_PARAMETER: ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "context error invalid parameter"); ++ break; ++ default: ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "context error code"); ++ break; ++ } ++ ++ return 0; ++} ++ ++static void* ++image_address (void *image, grub_efi_uint64_t sz, grub_efi_uint64_t adr) ++{ ++ if (adr > sz) ++ return NULL; ++ ++ return ((grub_uint8_t*)image + adr); ++} ++ ++static int ++image_is_64_bit (grub_pe_header_t *pe_hdr) ++{ ++ /* .Magic is the same offset in all cases */ ++ if (pe_hdr->pe32plus.optional_header.magic == GRUB_PE32_PE64_MAGIC) ++ return 1; ++ return 0; ++} ++ ++static const grub_uint16_t machine_type = ++#if defined(__x86_64__) ++ GRUB_PE32_MACHINE_X86_64; ++#elif defined(__aarch64__) ++ GRUB_PE32_MACHINE_ARM64; ++#elif defined(__arm__) ++ GRUB_PE32_MACHINE_ARMTHUMB_MIXED; ++#elif defined(__i386__) || defined(__i486__) || defined(__i686__) ++ GRUB_PE32_MACHINE_I386; ++#elif defined(__ia64__) ++ GRUB_PE32_MACHINE_IA64; ++#else ++#error this architecture is not supported by grub2 ++#endif ++ ++static grub_efi_status_t ++relocate_coff (pe_coff_loader_image_context_t *context, ++ struct grub_pe32_section_table *section, ++ void *orig, void *data) ++{ ++ struct grub_pe32_data_directory *reloc_base, *reloc_base_end; ++ grub_efi_uint64_t adjust; ++ struct grub_pe32_fixup_block *reloc, *reloc_end; ++ char *fixup, *fixup_base, *fixup_data = NULL; ++ grub_efi_uint16_t *fixup_16; ++ grub_efi_uint32_t *fixup_32; ++ grub_efi_uint64_t *fixup_64; ++ grub_efi_uint64_t size = context->image_size; ++ void *image_end = (char *)orig + size; ++ int n = 0; ++ ++ if (image_is_64_bit (context->pe_hdr)) ++ context->pe_hdr->pe32plus.optional_header.image_base = ++ (grub_uint64_t)(unsigned long)data; ++ else ++ context->pe_hdr->pe32.optional_header.image_base = ++ (grub_uint32_t)(unsigned long)data; ++ ++ /* Alright, so here's how this works: ++ * ++ * context->reloc_dir gives us two things: ++ * - the VA the table of base relocation blocks are (maybe) to be ++ * mapped at (reloc_dir->rva) ++ * - the virtual size (reloc_dir->size) ++ * ++ * The .reloc section (section here) gives us some other things: ++ * - the name! kind of. (section->name) ++ * - the virtual size (section->virtual_size), which should be the same ++ * as RelocDir->Size ++ * - the virtual address (section->virtual_address) ++ * - the file section size (section->raw_data_size), which is ++ * a multiple of optional_header->file_alignment. Only useful for image ++ * validation, not really useful for iteration bounds. ++ * - the file address (section->raw_data_offset) ++ * - a bunch of stuff we don't use that's 0 in our binaries usually ++ * - Flags (section->characteristics) ++ * ++ * and then the thing that's actually at the file address is an array ++ * of struct grub_pe32_fixup_block structs with some values packed behind ++ * them. The block_size field of this structure includes the ++ * structure itself, and adding it to that structure's address will ++ * yield the next entry in the array. ++ */ ++ ++ reloc_base = image_address (orig, size, section->raw_data_offset); ++ reloc_base_end = image_address (orig, size, section->raw_data_offset ++ + section->virtual_size - 1); ++ ++ grub_dprintf ("chain", "reloc_base %p reloc_base_end %p\n", reloc_base, ++ reloc_base_end); ++ ++ if (!reloc_base && !reloc_base_end) ++ return GRUB_EFI_SUCCESS; ++ ++ if (!reloc_base || !reloc_base_end) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "Reloc table overflows binary"); ++ return GRUB_EFI_UNSUPPORTED; ++ } ++ ++ adjust = (grub_uint64_t)data - context->image_address; ++ if (adjust == 0) ++ return GRUB_EFI_SUCCESS; ++ ++ while (reloc_base < reloc_base_end) ++ { ++ grub_uint16_t *entry; ++ reloc = (struct grub_pe32_fixup_block *)((char*)reloc_base); ++ ++ if ((reloc_base->size == 0) || ++ (reloc_base->size > context->reloc_dir->size)) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, ++ "Reloc %d block size %d is invalid\n", n, ++ reloc_base->size); ++ return GRUB_EFI_UNSUPPORTED; ++ } ++ ++ entry = &reloc->entries[0]; ++ reloc_end = (struct grub_pe32_fixup_block *) ++ ((char *)reloc_base + reloc_base->size); ++ ++ if ((void *)reloc_end < data || (void *)reloc_end > image_end) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "Reloc entry %d overflows binary", ++ n); ++ return GRUB_EFI_UNSUPPORTED; ++ } ++ ++ fixup_base = image_address(data, size, reloc_base->rva); ++ ++ if (!fixup_base) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "Reloc %d Invalid fixupbase", n); ++ return GRUB_EFI_UNSUPPORTED; ++ } ++ ++ while ((void *)entry < (void *)reloc_end) ++ { ++ fixup = fixup_base + (*entry & 0xFFF); ++ switch ((*entry) >> 12) ++ { ++ case GRUB_PE32_REL_BASED_ABSOLUTE: ++ break; ++ case GRUB_PE32_REL_BASED_HIGH: ++ fixup_16 = (grub_uint16_t *)fixup; ++ *fixup_16 = (grub_uint16_t) ++ (*fixup_16 + ((grub_uint16_t)((grub_uint32_t)adjust >> 16))); ++ if (fixup_data != NULL) ++ { ++ *(grub_uint16_t *) fixup_data = *fixup_16; ++ fixup_data = fixup_data + sizeof (grub_uint16_t); ++ } ++ break; ++ case GRUB_PE32_REL_BASED_LOW: ++ fixup_16 = (grub_uint16_t *)fixup; ++ *fixup_16 = (grub_uint16_t) (*fixup_16 + (grub_uint16_t)adjust); ++ if (fixup_data != NULL) ++ { ++ *(grub_uint16_t *) fixup_data = *fixup_16; ++ fixup_data = fixup_data + sizeof (grub_uint16_t); ++ } ++ break; ++ case GRUB_PE32_REL_BASED_HIGHLOW: ++ fixup_32 = (grub_uint32_t *)fixup; ++ *fixup_32 = *fixup_32 + (grub_uint32_t)adjust; ++ if (fixup_data != NULL) ++ { ++ fixup_data = (char *)ALIGN_UP ((grub_addr_t)fixup_data, sizeof (grub_uint32_t)); ++ *(grub_uint32_t *) fixup_data = *fixup_32; ++ fixup_data += sizeof (grub_uint32_t); ++ } ++ break; ++ case GRUB_PE32_REL_BASED_DIR64: ++ fixup_64 = (grub_uint64_t *)fixup; ++ *fixup_64 = *fixup_64 + (grub_uint64_t)adjust; ++ if (fixup_data != NULL) ++ { ++ fixup_data = (char *)ALIGN_UP ((grub_addr_t)fixup_data, sizeof (grub_uint64_t)); ++ *(grub_uint64_t *) fixup_data = *fixup_64; ++ fixup_data += sizeof (grub_uint64_t); ++ } ++ break; ++ default: ++ grub_error (GRUB_ERR_BAD_ARGUMENT, ++ "Reloc %d unknown relocation type %d", ++ n, (*entry) >> 12); ++ return GRUB_EFI_UNSUPPORTED; ++ } ++ entry += 1; ++ } ++ reloc_base = (struct grub_pe32_data_directory *)reloc_end; ++ n++; ++ } ++ ++ return GRUB_EFI_SUCCESS; ++} ++ ++static grub_efi_device_path_t * ++grub_efi_get_media_file_path (grub_efi_device_path_t *dp) ++{ ++ while (1) ++ { ++ grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp); ++ grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp); ++ ++ if (type == GRUB_EFI_END_DEVICE_PATH_TYPE) ++ break; ++ else if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE ++ && subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE) ++ return dp; ++ ++ dp = GRUB_EFI_NEXT_DEVICE_PATH (dp); ++ } ++ ++ return NULL; ++} ++ ++static grub_efi_boolean_t ++handle_image (void *data, grub_efi_uint32_t datasize) ++{ ++ grub_efi_boot_services_t *b; ++ grub_efi_loaded_image_t *li, li_bak; ++ grub_efi_status_t efi_status; ++ char *buffer = NULL; ++ char *buffer_aligned = NULL; ++ grub_efi_uint32_t i, size; ++ struct grub_pe32_section_table *section; ++ char *base, *end; ++ pe_coff_loader_image_context_t context; ++ grub_uint32_t section_alignment; ++ grub_uint32_t buffer_size; ++ ++ b = grub_efi_system_table->boot_services; ++ ++ if (read_header (data, datasize, &context)) ++ { ++ grub_dprintf ("chain", "Succeed to read header\n"); ++ } ++ else ++ { ++ grub_dprintf ("chain", "Failed to read header\n"); ++ goto error_exit; ++ } ++ ++ section_alignment = context.section_alignment; ++ buffer_size = context.image_size + section_alignment; ++ ++ efi_status = efi_call_3 (b->allocate_pool, GRUB_EFI_LOADER_DATA, ++ buffer_size, &buffer); ++ ++ if (efi_status != GRUB_EFI_SUCCESS) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); ++ goto error_exit; ++ } ++ ++ buffer_aligned = (char *)ALIGN_UP ((grub_addr_t)buffer, section_alignment); ++ ++ if (!buffer_aligned) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); ++ goto error_exit; ++ } ++ ++ grub_memcpy (buffer_aligned, data, context.size_of_headers); ++ ++ char *reloc_base, *reloc_base_end; ++ reloc_base = image_address (buffer_aligned, datasize, ++ context.reloc_dir->rva); ++ /* RelocBaseEnd here is the address of the last byte of the table */ ++ reloc_base_end = image_address (buffer_aligned, datasize, ++ context.reloc_dir->rva ++ + context.reloc_dir->size - 1); ++ struct grub_pe32_section_table *reloc_section = NULL; ++ ++ section = context.first_section; ++ for (i = 0; i < context.number_of_sections; i++, section++) ++ { ++ size = section->virtual_size; ++ if (size > section->raw_data_size) ++ size = section->raw_data_size; ++ ++ base = image_address (buffer_aligned, context.image_size, ++ section->virtual_address); ++ end = image_address (buffer_aligned, context.image_size, ++ section->virtual_address + size - 1); ++ ++ ++ /* We do want to process .reloc, but it's often marked ++ * discardable, so we don't want to memcpy it. */ ++ if (grub_memcmp (section->name, ".reloc\0\0", 8) == 0) ++ { ++ if (reloc_section) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, ++ "Image has multiple relocation sections"); ++ goto error_exit; ++ } ++ ++ /* If it has nonzero sizes, and our bounds check ++ * made sense, and the VA and size match RelocDir's ++ * versions, then we believe in this section table. */ ++ if (section->raw_data_size && section->virtual_size && ++ base && end && reloc_base == base && reloc_base_end == end) ++ { ++ reloc_section = section; ++ } ++ } ++ ++ if (section->characteristics && GRUB_PE32_SCN_MEM_DISCARDABLE) ++ continue; ++ ++ if (!base || !end) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid section size"); ++ goto error_exit; ++ } ++ ++ if (section->virtual_address < context.size_of_headers || ++ section->raw_data_offset < context.size_of_headers) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, ++ "Section %d is inside image headers", i); ++ goto error_exit; ++ } ++ ++ if (section->raw_data_size > 0) ++ grub_memcpy (base, (grub_efi_uint8_t*)data + section->raw_data_offset, ++ size); ++ ++ if (size < section->virtual_size) ++ grub_memset (base + size, 0, section->virtual_size - size); ++ ++ grub_dprintf ("chain", "copied section %s\n", section->name); ++ } ++ ++ /* 5 == EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC */ ++ if (context.number_of_rva_and_sizes <= 5) ++ { ++ grub_dprintf ("chain", "image has no relocation entry\n"); ++ goto error_exit; ++ } ++ ++ if (context.reloc_dir->size && reloc_section) ++ { ++ /* run the relocation fixups */ ++ efi_status = relocate_coff (&context, reloc_section, data, ++ buffer_aligned); ++ ++ if (efi_status != GRUB_EFI_SUCCESS) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "relocation failed"); ++ goto error_exit; ++ } ++ } ++ ++ entry_point = image_address (buffer_aligned, context.image_size, ++ context.entry_point); ++ ++ if (!entry_point) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid entry point"); ++ goto error_exit; ++ } ++ ++ li = grub_efi_get_loaded_image (grub_efi_image_handle); ++ if (!li) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "no loaded image available"); ++ goto error_exit; ++ } ++ ++ grub_memcpy (&li_bak, li, sizeof (grub_efi_loaded_image_t)); ++ li->image_base = buffer_aligned; ++ li->image_size = context.image_size; ++ li->load_options = cmdline; ++ li->load_options_size = cmdline_len; ++ li->file_path = grub_efi_get_media_file_path (file_path); ++ li->device_handle = dev_handle; ++ if (li->file_path) ++ { ++ grub_printf ("file path: "); ++ grub_efi_print_device_path (li->file_path); ++ } ++ else ++ { ++ grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching file path found"); ++ goto error_exit; ++ } ++ ++ efi_status = efi_call_2 (entry_point, grub_efi_image_handle, ++ grub_efi_system_table); ++ ++ grub_memcpy (li, &li_bak, sizeof (grub_efi_loaded_image_t)); ++ efi_status = efi_call_1 (b->free_pool, buffer); ++ ++ return 1; ++ ++error_exit: ++ if (buffer) ++ efi_call_1 (b->free_pool, buffer); ++ ++ return 0; ++} ++ ++static grub_err_t ++grub_secureboot_chainloader_unload (void) ++{ ++ grub_efi_boot_services_t *b; ++ ++ b = grub_efi_system_table->boot_services; ++ efi_call_2 (b->free_pages, address, pages); ++ grub_free (file_path); ++ grub_free (cmdline); ++ cmdline = 0; ++ file_path = 0; ++ dev_handle = 0; ++ ++ grub_dl_unref (my_mod); ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_secureboot_chainloader_boot (void) ++{ ++ handle_image ((void *)address, fsize); ++ grub_loader_unset (); ++ return grub_errno; ++} ++ + static grub_err_t + grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) + { + grub_file_t file = 0; +- grub_ssize_t size; + grub_efi_status_t status; + grub_efi_boot_services_t *b; + grub_device_t dev = 0; +@@ -204,7 +723,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + grub_efi_loaded_image_t *loaded_image; + char *filename; + void *boot_image = 0; +- grub_efi_handle_t dev_handle = 0; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); +@@ -216,9 +734,36 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + address = 0; + image_handle = 0; + file_path = 0; ++ dev_handle = 0; + + b = grub_efi_system_table->boot_services; + ++ if (argc > 1) ++ { ++ int i; ++ grub_efi_char16_t *p16; ++ ++ for (i = 1, cmdline_len = 0; i < argc; i++) ++ cmdline_len += grub_strlen (argv[i]) + 1; ++ ++ cmdline_len *= sizeof (grub_efi_char16_t); ++ cmdline = p16 = grub_malloc (cmdline_len); ++ if (! cmdline) ++ goto fail; ++ ++ for (i = 1; i < argc; i++) ++ { ++ char *p8; ++ ++ p8 = argv[i]; ++ while (*p8) ++ *(p16++) = *(p8++); ++ ++ *(p16++) = ' '; ++ } ++ *(--p16) = 0; ++ } ++ + file = grub_file_open (filename); + if (! file) + goto fail; +@@ -267,14 +812,14 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + grub_printf ("file path: "); + grub_efi_print_device_path (file_path); + +- size = grub_file_size (file); +- if (!size) ++ fsize = grub_file_size (file); ++ if (!fsize) + { + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); + goto fail; + } +- pages = (((grub_efi_uintn_t) size + ((1 << 12) - 1)) >> 12); ++ pages = (((grub_efi_uintn_t) fsize + ((1 << 12) - 1)) >> 12); + + status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES, + GRUB_EFI_LOADER_CODE, +@@ -288,7 +833,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + } + + boot_image = (void *) ((grub_addr_t) address); +- if (grub_file_read (file, boot_image, size) != size) ++ if (grub_file_read (file, boot_image, fsize) != fsize) + { + if (grub_errno == GRUB_ERR_NONE) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), +@@ -298,7 +843,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + } + + #if defined (__i386__) || defined (__x86_64__) +- if (size >= (grub_ssize_t) sizeof (struct grub_macho_fat_header)) ++ if (fsize >= (grub_ssize_t) sizeof (struct grub_macho_fat_header)) + { + struct grub_macho_fat_header *head = boot_image; + if (head->magic +@@ -307,6 +852,14 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + grub_uint32_t i; + struct grub_macho_fat_arch *archs + = (struct grub_macho_fat_arch *) (head + 1); ++ ++ if (grub_efi_secure_boot()) ++ { ++ grub_error (GRUB_ERR_BAD_OS, ++ "MACHO binaries are forbidden with Secure Boot"); ++ goto fail; ++ } ++ + for (i = 0; i < grub_cpu_to_le32 (head->nfat_arch); i++) + { + if (GRUB_MACHO_CPUTYPE_IS_HOST_CURRENT (archs[i].cputype)) +@@ -321,21 +874,28 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + > ~grub_cpu_to_le32 (archs[i].size) + || grub_cpu_to_le32 (archs[i].offset) + + grub_cpu_to_le32 (archs[i].size) +- > (grub_size_t) size) ++ > (grub_size_t) fsize) + { + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); + goto fail; + } + boot_image = (char *) boot_image + grub_cpu_to_le32 (archs[i].offset); +- size = grub_cpu_to_le32 (archs[i].size); ++ fsize = grub_cpu_to_le32 (archs[i].size); + } + } + #endif + ++ if (grub_linuxefi_secure_validate((void *)address, fsize)) ++ { ++ grub_file_close (file); ++ grub_loader_set (grub_secureboot_chainloader_boot, ++ grub_secureboot_chainloader_unload, 0); ++ return 0; ++ } ++ + status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path, +- boot_image, size, +- &image_handle); ++ boot_image, fsize, &image_handle); + if (status != GRUB_EFI_SUCCESS) + { + if (status == GRUB_EFI_OUT_OF_RESOURCES) +@@ -357,33 +917,10 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + } + loaded_image->device_handle = dev_handle; + +- if (argc > 1) ++ if (cmdline) + { +- int i, len; +- grub_efi_char16_t *p16; +- +- for (i = 1, len = 0; i < argc; i++) +- len += grub_strlen (argv[i]) + 1; +- +- len *= sizeof (grub_efi_char16_t); +- cmdline = p16 = grub_malloc (len); +- if (! cmdline) +- goto fail; +- +- for (i = 1; i < argc; i++) +- { +- char *p8; +- +- p8 = argv[i]; +- while (*p8) +- *(p16++) = *(p8++); +- +- *(p16++) = ' '; +- } +- *(--p16) = 0; +- + loaded_image->load_options = cmdline; +- loaded_image->load_options_size = len; ++ loaded_image->load_options_size = cmdline_len; + } + + grub_file_close (file); +@@ -405,6 +942,9 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + if (address) + efi_call_2 (b->free_pages, address, pages); + ++ if (cmdline) ++ grub_free (cmdline); ++ + grub_dl_unref (my_mod); + + return grub_errno; +diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h +index f79c36c026e..f79782e1bde 100644 +--- a/include/grub/efi/pe32.h ++++ b/include/grub/efi/pe32.h +@@ -212,7 +212,11 @@ struct grub_pe64_optional_header + struct grub_pe32_section_table + { + char name[8]; +- grub_uint32_t virtual_size; ++ union ++ { ++ grub_uint32_t physical_address; ++ grub_uint32_t virtual_size; ++ }; + grub_uint32_t virtual_address; + grub_uint32_t raw_data_size; + grub_uint32_t raw_data_offset; +@@ -263,6 +267,20 @@ struct grub_pe32_header + #endif + }; + ++struct grub_pe32_header_32 ++{ ++ char signature[GRUB_PE32_SIGNATURE_SIZE]; ++ struct grub_pe32_coff_header coff_header; ++ struct grub_pe32_optional_header optional_header; ++}; ++ ++struct grub_pe32_header_64 ++{ ++ char signature[GRUB_PE32_SIGNATURE_SIZE]; ++ struct grub_pe32_coff_header coff_header; ++ struct grub_pe64_optional_header optional_header; ++}; ++ + struct grub_pe32_fixup_block + { + grub_uint32_t page_rva; diff --git a/SOURCES/0221-Make-any-of-the-loaders-that-link-in-efi-mode-honor-.patch b/SOURCES/0221-Make-any-of-the-loaders-that-link-in-efi-mode-honor-.patch new file mode 100644 index 0000000..7b98145 --- /dev/null +++ b/SOURCES/0221-Make-any-of-the-loaders-that-link-in-efi-mode-honor-.patch @@ -0,0 +1,492 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 6 Oct 2015 16:09:25 -0400 +Subject: [PATCH] Make any of the loaders that link in efi mode honor secure + boot. + +And in this case "honor" means "even if somebody does link this in, they +won't register commands if SB is enabled." + +Signed-off-by: Peter Jones +--- + grub-core/Makefile.core.def | 2 ++ + grub-core/commands/iorw.c | 7 +++++ + grub-core/commands/memrw.c | 7 +++++ + grub-core/kern/efi/efi.c | 28 ------------------ + grub-core/kern/efi/sb.c | 58 ++++++++++++++++++++++++++++++++++++++ + grub-core/loader/efi/appleloader.c | 7 +++++ + grub-core/loader/efi/chainloader.c | 1 + + grub-core/loader/i386/bsd.c | 7 +++++ + grub-core/loader/i386/linux.c | 7 +++++ + grub-core/loader/i386/pc/linux.c | 7 +++++ + grub-core/loader/multiboot.c | 7 +++++ + grub-core/loader/xnu.c | 7 +++++ + include/grub/efi/efi.h | 1 - + include/grub/efi/sb.h | 29 +++++++++++++++++++ + include/grub/ia64/linux.h | 0 + include/grub/mips/linux.h | 0 + include/grub/powerpc/linux.h | 0 + include/grub/sparc64/linux.h | 0 + grub-core/Makefile.am | 1 + + 19 files changed, 147 insertions(+), 29 deletions(-) + create mode 100644 grub-core/kern/efi/sb.c + create mode 100644 include/grub/efi/sb.h + create mode 100644 include/grub/ia64/linux.h + create mode 100644 include/grub/mips/linux.h + create mode 100644 include/grub/powerpc/linux.h + create mode 100644 include/grub/sparc64/linux.h + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 4fc74393335..b340ceeec7f 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -175,6 +175,8 @@ kernel = { + efi = term/efi/console.c; + efi = lib/envblk.c; + ++ common = kern/efi/sb.c; ++ + x86 = kern/i386/tsc.c; + + i386_efi = kern/i386/efi/init.c; +diff --git a/grub-core/commands/iorw.c b/grub-core/commands/iorw.c +index a0c164e54f0..41a7f3f0466 100644 +--- a/grub-core/commands/iorw.c ++++ b/grub-core/commands/iorw.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -118,6 +119,9 @@ grub_cmd_write (grub_command_t cmd, int argc, char **argv) + + GRUB_MOD_INIT(memrw) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + cmd_read_byte = + grub_register_extcmd ("inb", grub_cmd_read, 0, + N_("PORT"), N_("Read 8-bit value from PORT."), +@@ -146,6 +150,9 @@ GRUB_MOD_INIT(memrw) + + GRUB_MOD_FINI(memrw) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + grub_unregister_extcmd (cmd_read_byte); + grub_unregister_extcmd (cmd_read_word); + grub_unregister_extcmd (cmd_read_dword); +diff --git a/grub-core/commands/memrw.c b/grub-core/commands/memrw.c +index 98769eadb34..088cbe9e2bc 100644 +--- a/grub-core/commands/memrw.c ++++ b/grub-core/commands/memrw.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -120,6 +121,9 @@ grub_cmd_write (grub_command_t cmd, int argc, char **argv) + + GRUB_MOD_INIT(memrw) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + cmd_read_byte = + grub_register_extcmd ("read_byte", grub_cmd_read, 0, + N_("ADDR"), N_("Read 8-bit value from ADDR."), +@@ -148,6 +152,9 @@ GRUB_MOD_INIT(memrw) + + GRUB_MOD_FINI(memrw) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + grub_unregister_extcmd (cmd_read_byte); + grub_unregister_extcmd (cmd_read_word); + grub_unregister_extcmd (cmd_read_dword); +diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c +index c80d85b677e..7dfe2ef1455 100644 +--- a/grub-core/kern/efi/efi.c ++++ b/grub-core/kern/efi/efi.c +@@ -260,34 +260,6 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid, + return NULL; + } + +-grub_efi_boolean_t +-grub_efi_secure_boot (void) +-{ +- grub_efi_guid_t efi_var_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID; +- grub_size_t datasize; +- char *secure_boot = NULL; +- char *setup_mode = NULL; +- grub_efi_boolean_t ret = 0; +- +- secure_boot = grub_efi_get_variable("SecureBoot", &efi_var_guid, &datasize); +- +- if (datasize != 1 || !secure_boot) +- goto out; +- +- setup_mode = grub_efi_get_variable("SetupMode", &efi_var_guid, &datasize); +- +- if (datasize != 1 || !setup_mode) +- goto out; +- +- if (*secure_boot && !*setup_mode) +- ret = 1; +- +- out: +- grub_free (secure_boot); +- grub_free (setup_mode); +- return ret; +-} +- + #pragma GCC diagnostic ignored "-Wcast-align" + + /* Search the mods section from the PE32/PE32+ image. This code uses +diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c +new file mode 100644 +index 00000000000..a41b6c5b851 +--- /dev/null ++++ b/grub-core/kern/efi/sb.c +@@ -0,0 +1,58 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2014 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++int ++grub_efi_secure_boot (void) ++{ ++#ifdef GRUB_MACHINE_EFI ++ grub_efi_guid_t efi_var_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID; ++ grub_size_t datasize; ++ char *secure_boot = NULL; ++ char *setup_mode = NULL; ++ grub_efi_boolean_t ret = 0; ++ ++ secure_boot = grub_efi_get_variable("SecureBoot", &efi_var_guid, &datasize); ++ ++ if (datasize != 1 || !secure_boot) ++ goto out; ++ ++ setup_mode = grub_efi_get_variable("SetupMode", &efi_var_guid, &datasize); ++ ++ if (datasize != 1 || !setup_mode) ++ goto out; ++ ++ if (*secure_boot && !*setup_mode) ++ ret = 1; ++ ++ out: ++ grub_free (secure_boot); ++ grub_free (setup_mode); ++ return ret; ++#else ++ return 0; ++#endif ++} +diff --git a/grub-core/loader/efi/appleloader.c b/grub-core/loader/efi/appleloader.c +index 74888c463ba..69c2a10d351 100644 +--- a/grub-core/loader/efi/appleloader.c ++++ b/grub-core/loader/efi/appleloader.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -227,6 +228,9 @@ static grub_command_t cmd; + + GRUB_MOD_INIT(appleloader) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + cmd = grub_register_command ("appleloader", grub_cmd_appleloader, + N_("[OPTS]"), + /* TRANSLATORS: This command is used on EFI to +@@ -238,5 +242,8 @@ GRUB_MOD_INIT(appleloader) + + GRUB_MOD_FINI(appleloader) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + grub_unregister_command (cmd); + } +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index 87a91e16f17..aee8e6becf6 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + #include + #include + #include +diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c +index 8f691e0e2d1..b671f59b62a 100644 +--- a/grub-core/loader/i386/bsd.c ++++ b/grub-core/loader/i386/bsd.c +@@ -38,6 +38,7 @@ + #ifdef GRUB_MACHINE_PCBIOS + #include + #endif ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -2111,6 +2112,9 @@ static grub_command_t cmd_netbsd_module_elf, cmd_openbsd_ramdisk; + + GRUB_MOD_INIT (bsd) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + /* Net and OpenBSD kernels are often compressed. */ + grub_dl_load ("gzio"); + +@@ -2150,6 +2154,9 @@ GRUB_MOD_INIT (bsd) + + GRUB_MOD_FINI (bsd) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + grub_unregister_extcmd (cmd_freebsd); + grub_unregister_extcmd (cmd_openbsd); + grub_unregister_extcmd (cmd_netbsd); +diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c +index 2ae176315b6..bd37c69b5d0 100644 +--- a/grub-core/loader/i386/linux.c ++++ b/grub-core/loader/i386/linux.c +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -1137,6 +1138,9 @@ static grub_command_t cmd_linux, cmd_initrd; + + GRUB_MOD_INIT(linux) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + cmd_linux = grub_register_command ("linux", grub_cmd_linux, + 0, N_("Load Linux.")); + cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, +@@ -1146,6 +1150,9 @@ GRUB_MOD_INIT(linux) + + GRUB_MOD_FINI(linux) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + grub_unregister_command (cmd_linux); + grub_unregister_command (cmd_initrd); + } +diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c +index b481e466846..b19527e8e17 100644 +--- a/grub-core/loader/i386/pc/linux.c ++++ b/grub-core/loader/i386/pc/linux.c +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -469,6 +470,9 @@ static grub_command_t cmd_linux, cmd_initrd; + + GRUB_MOD_INIT(linux16) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + cmd_linux = + grub_register_command ("linux16", grub_cmd_linux, + 0, N_("Load Linux.")); +@@ -480,6 +484,9 @@ GRUB_MOD_INIT(linux16) + + GRUB_MOD_FINI(linux16) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + grub_unregister_command (cmd_linux); + grub_unregister_command (cmd_initrd); + } +diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c +index 4b71f336353..e4e696e8f89 100644 +--- a/grub-core/loader/multiboot.c ++++ b/grub-core/loader/multiboot.c +@@ -42,6 +42,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -383,6 +384,9 @@ static grub_command_t cmd_multiboot, cmd_module; + + GRUB_MOD_INIT(multiboot) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + cmd_multiboot = + #ifdef GRUB_USE_MULTIBOOT2 + grub_register_command ("multiboot2", grub_cmd_multiboot, +@@ -403,6 +407,9 @@ GRUB_MOD_INIT(multiboot) + + GRUB_MOD_FINI(multiboot) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + grub_unregister_command (cmd_multiboot); + grub_unregister_command (cmd_module); + } +diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c +index cdd9715cedd..faffccc9744 100644 +--- a/grub-core/loader/xnu.c ++++ b/grub-core/loader/xnu.c +@@ -33,6 +33,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -1466,6 +1467,9 @@ static grub_extcmd_t cmd_splash; + + GRUB_MOD_INIT(xnu) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + cmd_kernel = grub_register_command ("xnu_kernel", grub_cmd_xnu_kernel, 0, + N_("Load XNU image.")); + cmd_kernel64 = grub_register_command ("xnu_kernel64", grub_cmd_xnu_kernel64, +@@ -1506,6 +1510,9 @@ GRUB_MOD_INIT(xnu) + + GRUB_MOD_FINI(xnu) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + #ifndef GRUB_MACHINE_EMU + grub_unregister_command (cmd_resume); + #endif +diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h +index 22456327e13..9a2da0eb38d 100644 +--- a/include/grub/efi/efi.h ++++ b/include/grub/efi/efi.h +@@ -76,7 +76,6 @@ EXPORT_FUNC (grub_efi_set_variable) (const char *var, + const grub_efi_guid_t *guid, + void *data, + grub_size_t datasize); +-grub_efi_boolean_t EXPORT_FUNC (grub_efi_secure_boot) (void); + int + EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1, + const grub_efi_device_path_t *dp2); +diff --git a/include/grub/efi/sb.h b/include/grub/efi/sb.h +new file mode 100644 +index 00000000000..9629fbb0f9e +--- /dev/null ++++ b/include/grub/efi/sb.h +@@ -0,0 +1,29 @@ ++/* sb.h - declare functions for EFI Secure Boot support */ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_EFI_SB_HEADER ++#define GRUB_EFI_SB_HEADER 1 ++ ++#include ++#include ++ ++/* Functions. */ ++int EXPORT_FUNC (grub_efi_secure_boot) (void); ++ ++#endif /* ! GRUB_EFI_SB_HEADER */ +diff --git a/include/grub/ia64/linux.h b/include/grub/ia64/linux.h +new file mode 100644 +index 00000000000..e69de29bb2d +diff --git a/include/grub/mips/linux.h b/include/grub/mips/linux.h +new file mode 100644 +index 00000000000..e69de29bb2d +diff --git a/include/grub/powerpc/linux.h b/include/grub/powerpc/linux.h +new file mode 100644 +index 00000000000..e69de29bb2d +diff --git a/include/grub/sparc64/linux.h b/include/grub/sparc64/linux.h +new file mode 100644 +index 00000000000..e69de29bb2d +diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am +index cb7fd9f98e8..be29e327f77 100644 +--- a/grub-core/Makefile.am ++++ b/grub-core/Makefile.am +@@ -67,6 +67,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/command.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/device.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/disk.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/dl.h ++KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/sb.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env_private.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/err.h diff --git a/SOURCES/0222-Rework-linux-command.patch b/SOURCES/0222-Rework-linux-command.patch new file mode 100644 index 0000000..faab6c2 --- /dev/null +++ b/SOURCES/0222-Rework-linux-command.patch @@ -0,0 +1,104 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Sun, 9 Aug 2015 16:12:39 -0700 +Subject: [PATCH] Rework linux command + +We want a single buffer that contains the entire kernel image in order to +perform a TPM measurement. Allocate one and copy the entire kernel into it +before pulling out the individual blocks later on. +--- + grub-core/loader/i386/linux.c | 34 +++++++++++++++++++++------------- + 1 file changed, 21 insertions(+), 13 deletions(-) + +diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c +index bd37c69b5d0..53f74ae0685 100644 +--- a/grub-core/loader/i386/linux.c ++++ b/grub-core/loader/i386/linux.c +@@ -682,12 +682,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_file_t file = 0; + struct linux_kernel_header lh; + grub_uint8_t setup_sects; +- grub_size_t real_size, prot_size, prot_file_size; ++ grub_size_t real_size, prot_size, prot_file_size, kernel_offset; + grub_ssize_t len; + int i; + grub_size_t align, min_align; + int relocatable; + grub_uint64_t preferred_address = GRUB_LINUX_BZIMAGE_ADDR; ++ grub_uint8_t *kernel = NULL; + + grub_dl_ref (my_mod); + +@@ -701,7 +702,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + if (! file) + goto fail; + +- if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) ++ len = grub_file_size (file); ++ kernel = grub_malloc (len); ++ if (!kernel) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer")); ++ goto fail; ++ } ++ ++ if (grub_file_read (file, kernel, len) != len) + { + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), +@@ -709,6 +718,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + ++ grub_memcpy (&lh, kernel, sizeof (lh)); ++ kernel_offset = sizeof (lh); ++ + if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55)) + { + grub_error (GRUB_ERR_BAD_OS, "invalid magic number"); +@@ -808,13 +820,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + linux_params.ps_mouse = linux_params.padding10 = 0; + + len = sizeof (linux_params) - sizeof (lh); +- if (grub_file_read (file, (char *) &linux_params + sizeof (lh), len) != len) +- { +- if (!grub_errno) +- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), +- argv[0]); +- goto fail; +- } ++ ++ grub_memcpy (&linux_params + sizeof (lh), kernel + kernel_offset, len); ++ kernel_offset += len; + + linux_params.type_of_loader = GRUB_LINUX_BOOT_LOADER_TYPE; + +@@ -873,7 +881,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + + /* The other parameters are filled when booting. */ + +- grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE); ++ kernel_offset = real_size + GRUB_DISK_SECTOR_SIZE; + + grub_dprintf ("linux", "bzImage, setup=0x%x, size=0x%x\n", + (unsigned) real_size, (unsigned) prot_size); +@@ -1018,9 +1026,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + - (sizeof (LINUX_IMAGE) - 1)); + + len = prot_file_size; +- if (grub_file_read (file, prot_mode_mem, len) != len && !grub_errno) +- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), +- argv[0]); ++ grub_memcpy (prot_mode_mem, kernel + kernel_offset, len); + + if (grub_errno == GRUB_ERR_NONE) + { +@@ -1031,6 +1037,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + + fail: + ++ grub_free (kernel); ++ + if (file) + grub_file_close (file); + diff --git a/SOURCES/0223-Rework-linux16-command.patch b/SOURCES/0223-Rework-linux16-command.patch new file mode 100644 index 0000000..37c7671 --- /dev/null +++ b/SOURCES/0223-Rework-linux16-command.patch @@ -0,0 +1,153 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Sun, 9 Aug 2015 16:20:58 -0700 +Subject: [PATCH] Rework linux16 command + +We want a single buffer that contains the entire kernel image in order to +perform a TPM measurement. Allocate one and copy the entire kernel int it +before pulling out the individual blocks later on. +--- + grub-core/loader/i386/pc/linux.c | 54 +++++++++++++++++++++++----------------- + 1 file changed, 31 insertions(+), 23 deletions(-) + +diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c +index b19527e8e17..60bb31fbf0d 100644 +--- a/grub-core/loader/i386/pc/linux.c ++++ b/grub-core/loader/i386/pc/linux.c +@@ -124,13 +124,14 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_file_t file = 0; + struct linux_kernel_header lh; + grub_uint8_t setup_sects; +- grub_size_t real_size; ++ grub_size_t real_size, kernel_offset = 0; + grub_ssize_t len; + int i; + char *grub_linux_prot_chunk; + int grub_linux_is_bzimage; + grub_addr_t grub_linux_prot_target; + grub_err_t err; ++ grub_uint8_t *kernel = NULL; + + grub_dl_ref (my_mod); + +@@ -144,7 +145,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + if (! file) + goto fail; + +- if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) ++ len = grub_file_size (file); ++ kernel = grub_malloc (len); ++ if (!kernel) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer")); ++ goto fail; ++ } ++ ++ if (grub_file_read (file, kernel, len) != len) + { + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), +@@ -152,7 +161,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + +- if (lh.boot_flag != grub_cpu_to_le16 (0xaa55)) ++ grub_memcpy (&lh, kernel, sizeof (lh)); ++ kernel_offset = sizeof (lh); ++ ++ if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55)) + { + grub_error (GRUB_ERR_BAD_OS, "invalid magic number"); + goto fail; +@@ -170,7 +182,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + + maximal_cmdline_size = 256; + +- if (lh.header == grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE) ++ if (lh.header == grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE) + && grub_le_to_cpu16 (lh.version) >= 0x0200) + { + grub_linux_is_bzimage = (lh.loadflags & GRUB_LINUX_FLAG_BIG_KERNEL); +@@ -189,7 +201,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + + if (grub_le_to_cpu16 (lh.version) >= 0x0201) + { +- lh.heap_end_ptr = grub_cpu_to_le16 (GRUB_LINUX_HEAP_END_OFFSET); ++ lh.heap_end_ptr = grub_cpu_to_le32_compile_time (GRUB_LINUX_HEAP_END_OFFSET); + lh.loadflags |= GRUB_LINUX_FLAG_CAN_USE_HEAP; + } + +@@ -197,17 +209,17 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + lh.cmd_line_ptr = grub_linux_real_target + GRUB_LINUX_CL_OFFSET; + else + { +- lh.cl_magic = grub_cpu_to_le16 (GRUB_LINUX_CL_MAGIC); +- lh.cl_offset = grub_cpu_to_le16 (GRUB_LINUX_CL_OFFSET); +- lh.setup_move_size = grub_cpu_to_le16 (GRUB_LINUX_CL_OFFSET ++ lh.cl_magic = grub_cpu_to_le32_compile_time (GRUB_LINUX_CL_MAGIC); ++ lh.cl_offset = grub_cpu_to_le32_compile_time (GRUB_LINUX_CL_OFFSET); ++ lh.setup_move_size = grub_cpu_to_le32_compile_time (GRUB_LINUX_CL_OFFSET + + maximal_cmdline_size); + } + } + else + { + /* Your kernel is quite old... */ +- lh.cl_magic = grub_cpu_to_le16 (GRUB_LINUX_CL_MAGIC); +- lh.cl_offset = grub_cpu_to_le16 (GRUB_LINUX_CL_OFFSET); ++ lh.cl_magic = grub_cpu_to_le32_compile_time (GRUB_LINUX_CL_MAGIC); ++ lh.cl_offset = grub_cpu_to_le32_compile_time (GRUB_LINUX_CL_OFFSET); + + setup_sects = GRUB_LINUX_DEFAULT_SETUP_SECTS; + +@@ -312,15 +324,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_memmove (grub_linux_real_chunk, &lh, sizeof (lh)); + + len = real_size + GRUB_DISK_SECTOR_SIZE - sizeof (lh); +- if (grub_file_read (file, grub_linux_real_chunk + sizeof (lh), len) != len) +- { +- if (!grub_errno) +- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), +- argv[0]); +- goto fail; +- } ++ grub_memcpy (grub_linux_real_chunk + sizeof (lh), kernel + kernel_offset, ++ len); ++ kernel_offset += len; + +- if (lh.header != grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE) ++ if (lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE) + || grub_le_to_cpu16 (lh.version) < 0x0200) + /* Clear the heap space. */ + grub_memset (grub_linux_real_chunk +@@ -353,10 +361,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + } + + len = grub_linux16_prot_size; +- if (grub_file_read (file, grub_linux_prot_chunk, grub_linux16_prot_size) +- != (grub_ssize_t) grub_linux16_prot_size && !grub_errno) +- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), +- argv[0]); ++ grub_memcpy (grub_linux_prot_chunk, kernel + kernel_offset, len); ++ kernel_offset += len; + + if (grub_errno == GRUB_ERR_NONE) + { +@@ -366,6 +372,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + + fail: + ++ grub_free (kernel); ++ + if (file) + grub_file_close (file); + +@@ -405,7 +413,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + + lh = (struct linux_kernel_header *) grub_linux_real_chunk; + +- if (!(lh->header == grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE) ++ if (!(lh->header == grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE) + && grub_le_to_cpu16 (lh->version) >= 0x0200)) + { + grub_error (GRUB_ERR_BAD_OS, "the kernel is too old for initrd"); diff --git a/SOURCES/0224-Re-work-some-intricacies-of-PE-loading.patch b/SOURCES/0224-Re-work-some-intricacies-of-PE-loading.patch new file mode 100644 index 0000000..cce6e3c --- /dev/null +++ b/SOURCES/0224-Re-work-some-intricacies-of-PE-loading.patch @@ -0,0 +1,350 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 9 Jun 2016 12:22:29 -0400 +Subject: [PATCH] Re-work some intricacies of PE loading. + +The PE spec is not a well written document, and awesomely every place +where there's an ambiguous way to read something, Windows' bootmgfw.efi +takes a different read than either of them. +--- + grub-core/loader/efi/chainloader.c | 156 +++++++++++++++++++++++++++++-------- + include/grub/efi/pe32.h | 32 +++++++- + 2 files changed, 152 insertions(+), 36 deletions(-) + +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index aee8e6becf6..4b77a7d5adb 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -301,7 +301,7 @@ image_is_64_bit (grub_pe_header_t *pe_hdr) + return 0; + } + +-static const grub_uint16_t machine_type = ++static const grub_uint16_t machine_type __attribute__((__unused__)) = + #if defined(__x86_64__) + GRUB_PE32_MACHINE_X86_64; + #elif defined(__aarch64__) +@@ -367,10 +367,10 @@ relocate_coff (pe_coff_loader_image_context_t *context, + + reloc_base = image_address (orig, size, section->raw_data_offset); + reloc_base_end = image_address (orig, size, section->raw_data_offset +- + section->virtual_size - 1); ++ + section->virtual_size); + +- grub_dprintf ("chain", "reloc_base %p reloc_base_end %p\n", reloc_base, +- reloc_base_end); ++ grub_dprintf ("chain", "relocate_coff(): reloc_base %p reloc_base_end %p\n", ++ reloc_base, reloc_base_end); + + if (!reloc_base && !reloc_base_end) + return GRUB_EFI_SUCCESS; +@@ -507,12 +507,13 @@ handle_image (void *data, grub_efi_uint32_t datasize) + grub_efi_status_t efi_status; + char *buffer = NULL; + char *buffer_aligned = NULL; +- grub_efi_uint32_t i, size; ++ grub_efi_uint32_t i; + struct grub_pe32_section_table *section; + char *base, *end; + pe_coff_loader_image_context_t context; + grub_uint32_t section_alignment; + grub_uint32_t buffer_size; ++ int found_entry_point = 0; + + b = grub_efi_system_table->boot_services; + +@@ -526,8 +527,28 @@ handle_image (void *data, grub_efi_uint32_t datasize) + goto error_exit; + } + ++ /* ++ * The spec says, uselessly, of SectionAlignment: ++ * ===== ++ * The alignment (in bytes) of sections when they are loaded into ++ * memory. It must be greater than or equal to FileAlignment. The ++ * default is the page size for the architecture. ++ * ===== ++ * Which doesn't tell you whose responsibility it is to enforce the ++ * "default", or when. It implies that the value in the field must ++ * be > FileAlignment (also poorly defined), but it appears visual ++ * studio will happily write 512 for FileAlignment (its default) and ++ * 0 for SectionAlignment, intending to imply PAGE_SIZE. ++ * ++ * We only support one page size, so if it's zero, nerf it to 4096. ++ */ + section_alignment = context.section_alignment; ++ if (section_alignment == 0) ++ section_alignment = 4096; ++ + buffer_size = context.image_size + section_alignment; ++ grub_dprintf ("chain", "image size is %08lx, datasize is %08x\n", ++ context.image_size, datasize); + + efi_status = efi_call_3 (b->allocate_pool, GRUB_EFI_LOADER_DATA, + buffer_size, &buffer); +@@ -539,7 +560,6 @@ handle_image (void *data, grub_efi_uint32_t datasize) + } + + buffer_aligned = (char *)ALIGN_UP ((grub_addr_t)buffer, section_alignment); +- + if (!buffer_aligned) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); +@@ -548,27 +568,62 @@ handle_image (void *data, grub_efi_uint32_t datasize) + + grub_memcpy (buffer_aligned, data, context.size_of_headers); + ++ entry_point = image_address (buffer_aligned, context.image_size, ++ context.entry_point); ++ ++ grub_dprintf ("chain", "entry_point: %p\n", entry_point); ++ if (!entry_point) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid entry point"); ++ goto error_exit; ++ } ++ + char *reloc_base, *reloc_base_end; +- reloc_base = image_address (buffer_aligned, datasize, ++ grub_dprintf ("chain", "reloc_dir: %p reloc_size: 0x%08x\n", ++ (void *)(unsigned long long)context.reloc_dir->rva, ++ context.reloc_dir->size); ++ reloc_base = image_address (buffer_aligned, context.image_size, + context.reloc_dir->rva); + /* RelocBaseEnd here is the address of the last byte of the table */ +- reloc_base_end = image_address (buffer_aligned, datasize, ++ reloc_base_end = image_address (buffer_aligned, context.image_size, + context.reloc_dir->rva + + context.reloc_dir->size - 1); ++ grub_dprintf ("chain", "reloc_base: %p reloc_base_end: %p\n", ++ reloc_base, reloc_base_end); ++ + struct grub_pe32_section_table *reloc_section = NULL; + + section = context.first_section; + for (i = 0; i < context.number_of_sections; i++, section++) + { +- size = section->virtual_size; +- if (size > section->raw_data_size) +- size = section->raw_data_size; ++ char name[9]; + + base = image_address (buffer_aligned, context.image_size, + section->virtual_address); + end = image_address (buffer_aligned, context.image_size, +- section->virtual_address + size - 1); ++ section->virtual_address + section->virtual_size -1); + ++ grub_strncpy(name, section->name, 9); ++ name[8] = '\0'; ++ grub_dprintf ("chain", "Section %d \"%s\" at %p..%p\n", i, ++ name, base, end); ++ ++ if (end < base) ++ { ++ grub_dprintf ("chain", " base is %p but end is %p... bad.\n", ++ base, end); ++ grub_error (GRUB_ERR_BAD_ARGUMENT, ++ "Image has invalid negative size"); ++ goto error_exit; ++ } ++ ++ if (section->virtual_address <= context.entry_point && ++ (section->virtual_address + section->raw_data_size - 1) ++ > context.entry_point) ++ { ++ found_entry_point++; ++ grub_dprintf ("chain", " section contains entry point\n"); ++ } + + /* We do want to process .reloc, but it's often marked + * discardable, so we don't want to memcpy it. */ +@@ -587,21 +642,46 @@ handle_image (void *data, grub_efi_uint32_t datasize) + if (section->raw_data_size && section->virtual_size && + base && end && reloc_base == base && reloc_base_end == end) + { ++ grub_dprintf ("chain", " section is relocation section\n"); + reloc_section = section; + } ++ else ++ { ++ grub_dprintf ("chain", " section is not reloc section?\n"); ++ grub_dprintf ("chain", " rds: 0x%08x, vs: %08x\n", ++ section->raw_data_size, section->virtual_size); ++ grub_dprintf ("chain", " base: %p end: %p\n", base, end); ++ grub_dprintf ("chain", " reloc_base: %p reloc_base_end: %p\n", ++ reloc_base, reloc_base_end); ++ } + } + +- if (section->characteristics && GRUB_PE32_SCN_MEM_DISCARDABLE) +- continue; ++ grub_dprintf ("chain", " Section characteristics are %08x\n", ++ section->characteristics); ++ grub_dprintf ("chain", " Section virtual size: %08x\n", ++ section->virtual_size); ++ grub_dprintf ("chain", " Section raw_data size: %08x\n", ++ section->raw_data_size); ++ if (section->characteristics & GRUB_PE32_SCN_MEM_DISCARDABLE) ++ { ++ grub_dprintf ("chain", " Discarding section\n"); ++ continue; ++ } + + if (!base || !end) + { ++ grub_dprintf ("chain", " section is invalid\n"); + grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid section size"); + goto error_exit; + } + +- if (section->virtual_address < context.size_of_headers || +- section->raw_data_offset < context.size_of_headers) ++ if (section->characteristics & GRUB_PE32_SCN_CNT_UNINITIALIZED_DATA) ++ { ++ if (section->raw_data_size != 0) ++ grub_dprintf ("chain", " UNINITIALIZED_DATA section has data?\n"); ++ } ++ else if (section->virtual_address < context.size_of_headers || ++ section->raw_data_offset < context.size_of_headers) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, + "Section %d is inside image headers", i); +@@ -609,13 +689,24 @@ handle_image (void *data, grub_efi_uint32_t datasize) + } + + if (section->raw_data_size > 0) +- grub_memcpy (base, (grub_efi_uint8_t*)data + section->raw_data_offset, +- size); ++ { ++ grub_dprintf ("chain", " copying 0x%08x bytes to %p\n", ++ section->raw_data_size, base); ++ grub_memcpy (base, ++ (grub_efi_uint8_t*)data + section->raw_data_offset, ++ section->raw_data_size); ++ } + +- if (size < section->virtual_size) +- grub_memset (base + size, 0, section->virtual_size - size); ++ if (section->raw_data_size < section->virtual_size) ++ { ++ grub_dprintf ("chain", " padding with 0x%08x bytes at %p\n", ++ section->virtual_size - section->raw_data_size, ++ base + section->raw_data_size); ++ grub_memset (base + section->raw_data_size, 0, ++ section->virtual_size - section->raw_data_size); ++ } + +- grub_dprintf ("chain", "copied section %s\n", section->name); ++ grub_dprintf ("chain", " finished section %s\n", name); + } + + /* 5 == EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC */ +@@ -638,12 +729,15 @@ handle_image (void *data, grub_efi_uint32_t datasize) + } + } + +- entry_point = image_address (buffer_aligned, context.image_size, +- context.entry_point); +- +- if (!entry_point) ++ if (!found_entry_point) + { +- grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid entry point"); ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "entry point is not within sections"); ++ goto error_exit; ++ } ++ if (found_entry_point > 1) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "%d sections contain entry point", ++ found_entry_point); + goto error_exit; + } + +@@ -661,26 +755,24 @@ handle_image (void *data, grub_efi_uint32_t datasize) + li->load_options_size = cmdline_len; + li->file_path = grub_efi_get_media_file_path (file_path); + li->device_handle = dev_handle; +- if (li->file_path) +- { +- grub_printf ("file path: "); +- grub_efi_print_device_path (li->file_path); +- } +- else ++ if (!li->file_path) + { + grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching file path found"); + goto error_exit; + } + ++ grub_dprintf ("chain", "booting via entry point\n"); + efi_status = efi_call_2 (entry_point, grub_efi_image_handle, + grub_efi_system_table); + ++ grub_dprintf ("chain", "entry_point returned %ld\n", efi_status); + grub_memcpy (li, &li_bak, sizeof (grub_efi_loaded_image_t)); + efi_status = efi_call_1 (b->free_pool, buffer); + + return 1; + + error_exit: ++ grub_dprintf ("chain", "error_exit: grub_errno: %d\n", grub_errno); + if (buffer) + efi_call_1 (b->free_pool, buffer); + +diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h +index f79782e1bde..8396bde4917 100644 +--- a/include/grub/efi/pe32.h ++++ b/include/grub/efi/pe32.h +@@ -227,12 +227,18 @@ struct grub_pe32_section_table + grub_uint32_t characteristics; + }; + ++#define GRUB_PE32_SCN_TYPE_NO_PAD 0x00000008 + #define GRUB_PE32_SCN_CNT_CODE 0x00000020 + #define GRUB_PE32_SCN_CNT_INITIALIZED_DATA 0x00000040 +-#define GRUB_PE32_SCN_MEM_DISCARDABLE 0x02000000 +-#define GRUB_PE32_SCN_MEM_EXECUTE 0x20000000 +-#define GRUB_PE32_SCN_MEM_READ 0x40000000 +-#define GRUB_PE32_SCN_MEM_WRITE 0x80000000 ++#define GRUB_PE32_SCN_CNT_UNINITIALIZED_DATA 0x00000080 ++#define GRUB_PE32_SCN_LNK_OTHER 0x00000100 ++#define GRUB_PE32_SCN_LNK_INFO 0x00000200 ++#define GRUB_PE32_SCN_LNK_REMOVE 0x00000800 ++#define GRUB_PE32_SCN_LNK_COMDAT 0x00001000 ++#define GRUB_PE32_SCN_GPREL 0x00008000 ++#define GRUB_PE32_SCN_MEM_16BIT 0x00020000 ++#define GRUB_PE32_SCN_MEM_LOCKED 0x00040000 ++#define GRUB_PE32_SCN_MEM_PRELOAD 0x00080000 + + #define GRUB_PE32_SCN_ALIGN_1BYTES 0x00100000 + #define GRUB_PE32_SCN_ALIGN_2BYTES 0x00200000 +@@ -241,10 +247,28 @@ struct grub_pe32_section_table + #define GRUB_PE32_SCN_ALIGN_16BYTES 0x00500000 + #define GRUB_PE32_SCN_ALIGN_32BYTES 0x00600000 + #define GRUB_PE32_SCN_ALIGN_64BYTES 0x00700000 ++#define GRUB_PE32_SCN_ALIGN_128BYTES 0x00800000 ++#define GRUB_PE32_SCN_ALIGN_256BYTES 0x00900000 ++#define GRUB_PE32_SCN_ALIGN_512BYTES 0x00A00000 ++#define GRUB_PE32_SCN_ALIGN_1024BYTES 0x00B00000 ++#define GRUB_PE32_SCN_ALIGN_2048BYTES 0x00C00000 ++#define GRUB_PE32_SCN_ALIGN_4096BYTES 0x00D00000 ++#define GRUB_PE32_SCN_ALIGN_8192BYTES 0x00E00000 + + #define GRUB_PE32_SCN_ALIGN_SHIFT 20 + #define GRUB_PE32_SCN_ALIGN_MASK 7 + ++#define GRUB_PE32_SCN_LNK_NRELOC_OVFL 0x01000000 ++#define GRUB_PE32_SCN_MEM_DISCARDABLE 0x02000000 ++#define GRUB_PE32_SCN_MEM_NOT_CACHED 0x04000000 ++#define GRUB_PE32_SCN_MEM_NOT_PAGED 0x08000000 ++#define GRUB_PE32_SCN_MEM_SHARED 0x10000000 ++#define GRUB_PE32_SCN_MEM_EXECUTE 0x20000000 ++#define GRUB_PE32_SCN_MEM_READ 0x40000000 ++#define GRUB_PE32_SCN_MEM_WRITE 0x80000000 ++ ++ ++ + #define GRUB_PE32_SIGNATURE_SIZE 4 + + struct grub_pe32_header diff --git a/SOURCES/0225-Rework-even-more-of-efi-chainload-so-non-sb-cases-wo.patch b/SOURCES/0225-Rework-even-more-of-efi-chainload-so-non-sb-cases-wo.patch new file mode 100644 index 0000000..e099f5e --- /dev/null +++ b/SOURCES/0225-Rework-even-more-of-efi-chainload-so-non-sb-cases-wo.patch @@ -0,0 +1,385 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 10 Jun 2016 14:06:15 -0400 +Subject: [PATCH] Rework even more of efi chainload so non-sb cases work right. + +This ensures that if shim protocol is not loaded, or is loaded but shim +is disabled, we will fall back to a correct load method for the efi +chain loader. + +Here's what I tested with this version: + +results expected actual +------------------------------------------------------------ +sb + enabled + shim + fedora success success +sb + enabled + shim + win success success +sb + enabled + grub + fedora fail fail +sb + enabled + grub + win fail fail + +sb + mokdisabled + shim + fedora success success +sb + mokdisabled + shim + win success success +sb + mokdisabled + grub + fedora fail fail +sb + mokdisabled + grub + win fail fail + +sb disabled + shim + fedora success success* +sb disabled + shim + win success success* +sb disabled + grub + fedora success success +sb disabled + grub + win success success + +nosb + shim + fedora success success* +nosb + shim + win success success* +nosb + grub + fedora success success +nosb + grub + win success success + +* for some reason shim protocol is being installed in these cases, and I + can't see why, but I think it may be this firmware build returning an + erroneous value. But this effectively falls back to the mokdisabled + behavior, which works correctly, and the presence of the "grub" (i.e. + no shim) tests effectively tests the desired behavior here. + +Resolves: rhbz#1344512 + +Signed-off-by: Peter Jones +--- + grub-core/kern/efi/sb.c | 14 +++-- + grub-core/loader/arm64/linux.c | 4 +- + grub-core/loader/efi/chainloader.c | 117 ++++++++++++++++++++++--------------- + grub-core/loader/efi/linux.c | 13 +++-- + grub-core/loader/i386/efi/linux.c | 10 +++- + include/grub/efi/linux.h | 2 +- + 6 files changed, 100 insertions(+), 60 deletions(-) + +diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c +index a41b6c5b851..d74778b0cac 100644 +--- a/grub-core/kern/efi/sb.c ++++ b/grub-core/kern/efi/sb.c +@@ -36,14 +36,20 @@ grub_efi_secure_boot (void) + grub_efi_boolean_t ret = 0; + + secure_boot = grub_efi_get_variable("SecureBoot", &efi_var_guid, &datasize); +- + if (datasize != 1 || !secure_boot) +- goto out; ++ { ++ grub_dprintf ("secureboot", "No SecureBoot variable\n"); ++ goto out; ++ } ++ grub_dprintf ("secureboot", "SecureBoot: %d\n", *secure_boot); + + setup_mode = grub_efi_get_variable("SetupMode", &efi_var_guid, &datasize); +- + if (datasize != 1 || !setup_mode) +- goto out; ++ { ++ grub_dprintf ("secureboot", "No SetupMode variable\n"); ++ goto out; ++ } ++ grub_dprintf ("secureboot", "SetupMode: %d\n", *setup_mode); + + if (*secure_boot && !*setup_mode) + ret = 1; +diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c +index bdd9c9b4968..0452a20e98b 100644 +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -380,6 +380,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_file_t file = 0; + struct grub_arm64_linux_kernel_header lh; + struct grub_arm64_linux_pe_header *pe; ++ int rc; + + grub_dl_ref (my_mod); + +@@ -424,7 +425,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + + grub_dprintf ("linux", "kernel @ %p\n", kernel_addr); + +- if (!grub_linuxefi_secure_validate (kernel_addr, kernel_size)) ++ rc = grub_linuxefi_secure_validate (kernel_addr, kernel_size); ++ if (rc < 0) + { + grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]); + goto fail; +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index 4b77a7d5adb..3e89de9006c 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -182,7 +182,6 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename) + /* Fill the file path for the directory. */ + d = (grub_efi_device_path_t *) ((char *) file_path + + ((char *) d - (char *) dp)); +- grub_efi_print_device_path (d); + copy_file_path ((grub_efi_file_path_device_path_t *) d, + dir_start, dir_end - dir_start); + +@@ -252,10 +251,9 @@ read_header (void *data, grub_efi_uint32_t size, + grub_efi_status_t status; + + shim_lock = grub_efi_locate_protocol (&guid, NULL); +- + if (!shim_lock) + { +- grub_error (GRUB_ERR_BAD_ARGUMENT, "no shim lock protocol"); ++ grub_dprintf ("chain", "no shim lock protocol"); + return 0; + } + +@@ -280,7 +278,7 @@ read_header (void *data, grub_efi_uint32_t size, + break; + } + +- return 0; ++ return -1; + } + + static void* +@@ -514,18 +512,25 @@ handle_image (void *data, grub_efi_uint32_t datasize) + grub_uint32_t section_alignment; + grub_uint32_t buffer_size; + int found_entry_point = 0; ++ int rc; + + b = grub_efi_system_table->boot_services; + +- if (read_header (data, datasize, &context)) +- { +- grub_dprintf ("chain", "Succeed to read header\n"); +- } +- else ++ rc = read_header (data, datasize, &context); ++ if (rc < 0) + { + grub_dprintf ("chain", "Failed to read header\n"); + goto error_exit; + } ++ else if (rc == 0) ++ { ++ grub_dprintf ("chain", "Secure Boot is not enabled\n"); ++ return 0; ++ } ++ else ++ { ++ grub_dprintf ("chain", "Header read without error\n"); ++ } + + /* + * The spec says, uselessly, of SectionAlignment: +@@ -796,10 +801,56 @@ grub_secureboot_chainloader_unload (void) + return GRUB_ERR_NONE; + } + ++static grub_err_t ++grub_load_and_start_image(void *boot_image) ++{ ++ grub_efi_boot_services_t *b; ++ grub_efi_status_t status; ++ grub_efi_loaded_image_t *loaded_image; ++ ++ b = grub_efi_system_table->boot_services; ++ ++ status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path, ++ boot_image, fsize, &image_handle); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ if (status == GRUB_EFI_OUT_OF_RESOURCES) ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of resources"); ++ else ++ grub_error (GRUB_ERR_BAD_OS, "cannot load image"); ++ return -1; ++ } ++ ++ /* LoadImage does not set a device handler when the image is ++ loaded from memory, so it is necessary to set it explicitly here. ++ This is a mess. */ ++ loaded_image = grub_efi_get_loaded_image (image_handle); ++ if (! loaded_image) ++ { ++ grub_error (GRUB_ERR_BAD_OS, "no loaded image available"); ++ return -1; ++ } ++ loaded_image->device_handle = dev_handle; ++ ++ if (cmdline) ++ { ++ loaded_image->load_options = cmdline; ++ loaded_image->load_options_size = cmdline_len; ++ } ++ ++ return 0; ++} ++ + static grub_err_t + grub_secureboot_chainloader_boot (void) + { +- handle_image ((void *)address, fsize); ++ int rc; ++ rc = handle_image ((void *)address, fsize); ++ if (rc == 0) ++ { ++ grub_load_and_start_image((void *)address); ++ } ++ + grub_loader_unset (); + return grub_errno; + } +@@ -813,9 +864,9 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + grub_efi_boot_services_t *b; + grub_device_t dev = 0; + grub_efi_device_path_t *dp = 0; +- grub_efi_loaded_image_t *loaded_image; + char *filename; + void *boot_image = 0; ++ int rc; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); +@@ -902,9 +953,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + if (! file_path) + goto fail; + +- grub_printf ("file path: "); +- grub_efi_print_device_path (file_path); +- + fsize = grub_file_size (file); + if (!fsize) + { +@@ -979,51 +1027,28 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + } + #endif + +- if (grub_linuxefi_secure_validate((void *)address, fsize)) ++ rc = grub_linuxefi_secure_validate((void *)address, fsize); ++ grub_dprintf ("chain", "linuxefi_secure_validate: %d\n", rc); ++ if (rc > 0) + { + grub_file_close (file); + grub_loader_set (grub_secureboot_chainloader_boot, + grub_secureboot_chainloader_unload, 0); + return 0; + } +- +- status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path, +- boot_image, fsize, &image_handle); +- if (status != GRUB_EFI_SUCCESS) ++ else if (rc == 0) + { +- if (status == GRUB_EFI_OUT_OF_RESOURCES) +- grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of resources"); +- else +- grub_error (GRUB_ERR_BAD_OS, "cannot load image"); +- +- goto fail; +- } ++ grub_load_and_start_image(boot_image); ++ grub_file_close (file); ++ grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0); + +- /* LoadImage does not set a device handler when the image is +- loaded from memory, so it is necessary to set it explicitly here. +- This is a mess. */ +- loaded_image = grub_efi_get_loaded_image (image_handle); +- if (! loaded_image) +- { +- grub_error (GRUB_ERR_BAD_OS, "no loaded image available"); +- goto fail; +- } +- loaded_image->device_handle = dev_handle; +- +- if (cmdline) +- { +- loaded_image->load_options = cmdline; +- loaded_image->load_options_size = cmdline_len; ++ return 0; + } + + grub_file_close (file); + grub_device_close (dev); + +- grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0); +- return 0; +- +- fail: +- ++fail: + if (dev) + grub_device_close (dev); + +diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c +index aea378adf5c..8890bdf059a 100644 +--- a/grub-core/loader/efi/linux.c ++++ b/grub-core/loader/efi/linux.c +@@ -33,21 +33,24 @@ struct grub_efi_shim_lock + }; + typedef struct grub_efi_shim_lock grub_efi_shim_lock_t; + +-grub_efi_boolean_t ++int + grub_linuxefi_secure_validate (void *data, grub_uint32_t size) + { + grub_efi_guid_t guid = SHIM_LOCK_GUID; + grub_efi_shim_lock_t *shim_lock; ++ grub_efi_status_t status; + + shim_lock = grub_efi_locate_protocol(&guid, NULL); +- ++ grub_dprintf ("secureboot", "shim_lock: %p\n", shim_lock); + if (!shim_lock) +- return 1; ++ return 0; + +- if (shim_lock->verify(data, size) == GRUB_EFI_SUCCESS) ++ status = shim_lock->verify(data, size); ++ grub_dprintf ("secureboot", "shim_lock->verify(): %ld\n", status); ++ if (status == GRUB_EFI_SUCCESS) + return 1; + +- return 0; ++ return -1; + } + + typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *); +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 7ccf32d9d45..82f75b7f3ab 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -155,6 +155,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + struct linux_kernel_header lh; + grub_ssize_t len, start, filelen; + void *kernel = NULL; ++ int rc; + + grub_dl_ref (my_mod); + +@@ -180,13 +181,16 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + + if (grub_file_read (file, kernel, filelen) != filelen) + { +- grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"), argv[0]); ++ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"), ++ argv[0]); + goto fail; + } + +- if (! grub_linuxefi_secure_validate (kernel, filelen)) ++ rc = grub_linuxefi_secure_validate (kernel, filelen); ++ if (rc < 0) + { +- grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]); ++ grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), ++ argv[0]); + grub_free (kernel); + goto fail; + } +diff --git a/include/grub/efi/linux.h b/include/grub/efi/linux.h +index d9ede36773b..0033d9305a9 100644 +--- a/include/grub/efi/linux.h ++++ b/include/grub/efi/linux.h +@@ -22,7 +22,7 @@ + #include + #include + +-grub_efi_boolean_t ++int + EXPORT_FUNC(grub_linuxefi_secure_validate) (void *data, grub_uint32_t size); + grub_err_t + EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset, diff --git a/SOURCES/0226-linuxefi-fix-double-free-on-verification-failure.patch b/SOURCES/0226-linuxefi-fix-double-free-on-verification-failure.patch new file mode 100644 index 0000000..7d1b3c8 --- /dev/null +++ b/SOURCES/0226-linuxefi-fix-double-free-on-verification-failure.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 14 Jun 2016 09:50:25 -0400 +Subject: [PATCH] linuxefi: fix double free on verification failure. + +Signed-off-by: Peter Jones +--- + grub-core/loader/i386/efi/linux.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 82f75b7f3ab..010bf982d80 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -191,7 +191,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + { + grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), + argv[0]); +- grub_free (kernel); + goto fail; + } + diff --git a/SOURCES/0227-efi-chainloader-fix-wrong-sanity-check-in-relocate_c.patch b/SOURCES/0227-efi-chainloader-fix-wrong-sanity-check-in-relocate_c.patch new file mode 100644 index 0000000..9a00fab --- /dev/null +++ b/SOURCES/0227-efi-chainloader-fix-wrong-sanity-check-in-relocate_c.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Mon, 21 Nov 2016 15:34:00 +0100 +Subject: [PATCH] efi/chainloader: fix wrong sanity check in relocate_coff() + +In relocate_coff(), the relocation entries are parsed from the original +image (not the section-wise copied image). The original image is +pointed-to by the "orig" pointer. The current check + + (void *)reloc_end < data + +compares the addresses of independent memory allocations. "data" is a typo +here, it should be "orig". + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1347291 +Signed-off-by: Laszlo Ersek +Tested-by: Bogdan Costescu +Tested-by: Juan Orti +--- + grub-core/loader/efi/chainloader.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index 3e89de9006c..ed8c364789a 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -401,7 +401,7 @@ relocate_coff (pe_coff_loader_image_context_t *context, + reloc_end = (struct grub_pe32_fixup_block *) + ((char *)reloc_base + reloc_base->size); + +- if ((void *)reloc_end < data || (void *)reloc_end > image_end) ++ if ((void *)reloc_end < orig || (void *)reloc_end > image_end) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "Reloc entry %d overflows binary", + n); diff --git a/SOURCES/0228-efi-chainloader-truncate-overlong-relocation-section.patch b/SOURCES/0228-efi-chainloader-truncate-overlong-relocation-section.patch new file mode 100644 index 0000000..3bd7f11 --- /dev/null +++ b/SOURCES/0228-efi-chainloader-truncate-overlong-relocation-section.patch @@ -0,0 +1,110 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Wed, 23 Nov 2016 06:27:09 +0100 +Subject: [PATCH] efi/chainloader: truncate overlong relocation section + +The UEFI Windows 7 boot loader ("EFI/Microsoft/Boot/bootmgfw.efi", SHA1 +31b410e029bba87d2068c65a80b88882f9f8ea25) has inconsistent headers. + +Compare: + +> The Data Directory +> ... +> Entry 5 00000000000d9000 00000574 Base Relocation Directory [.reloc] + +Versus: + +> Sections: +> Idx Name Size VMA LMA File off ... +> ... +> 10 .reloc 00000e22 00000000100d9000 00000000100d9000 000a1800 ... + +That is, the size reported by the RelocDir entry (0x574) is smaller than +the virtual size of the .reloc section (0xe22). + +Quoting the grub2 debug log for the same: + +> chainloader.c:595: reloc_dir: 0xd9000 reloc_size: 0x00000574 +> chainloader.c:603: reloc_base: 0x7d208000 reloc_base_end: 0x7d208573 +> ... +> chainloader.c:620: Section 10 ".reloc" at 0x7d208000..0x7d208e21 +> chainloader.c:661: section is not reloc section? +> chainloader.c:663: rds: 0x00001000, vs: 00000e22 +> chainloader.c:664: base: 0x7d208000 end: 0x7d208e21 +> chainloader.c:666: reloc_base: 0x7d208000 reloc_base_end: 0x7d208573 +> chainloader.c:671: Section characteristics are 42000040 +> chainloader.c:673: Section virtual size: 00000e22 +> chainloader.c:675: Section raw_data size: 00001000 +> chainloader.c:678: Discarding section + +After hexdumping "bootmgfw.efi" and manually walking its relocation blocks +(yes, really), I determined that the (smaller) RelocDir value is correct. +The remaining area that extends up to the .reloc section size (== 0xe22 - +0x574 == 0x8ae bytes) exists as zero padding in the file. + +This zero padding shouldn't be passed to relocate_coff() for parsing. In +order to cope with it, split the handling of .reloc sections into the +following branches: + +- original case (equal size): original behavior (--> relocation + attempted), + +- overlong .reloc section (longer than reported by RelocDir): truncate the + section to the RelocDir size for the purposes of relocate_coff(), and + attempt relocation, + +- .reloc section is too short, or other checks fail: original behavior + (--> relocation not attempted). + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1347291 +Signed-off-by: Laszlo Ersek +--- + grub-core/loader/efi/chainloader.c | 26 +++++++++++++++++++++----- + 1 file changed, 21 insertions(+), 5 deletions(-) + +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index ed8c364789a..db1ffeefc93 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -596,7 +596,7 @@ handle_image (void *data, grub_efi_uint32_t datasize) + grub_dprintf ("chain", "reloc_base: %p reloc_base_end: %p\n", + reloc_base, reloc_base_end); + +- struct grub_pe32_section_table *reloc_section = NULL; ++ struct grub_pe32_section_table *reloc_section = NULL, fake_reloc_section; + + section = context.first_section; + for (i = 0; i < context.number_of_sections; i++, section++) +@@ -645,12 +645,28 @@ handle_image (void *data, grub_efi_uint32_t datasize) + * made sense, and the VA and size match RelocDir's + * versions, then we believe in this section table. */ + if (section->raw_data_size && section->virtual_size && +- base && end && reloc_base == base && reloc_base_end == end) ++ base && end && reloc_base == base) + { +- grub_dprintf ("chain", " section is relocation section\n"); +- reloc_section = section; ++ if (reloc_base_end == end) ++ { ++ grub_dprintf ("chain", " section is relocation section\n"); ++ reloc_section = section; ++ } ++ else if (reloc_base_end && reloc_base_end < end) ++ { ++ /* Bogus virtual size in the reloc section -- RelocDir ++ * reported a smaller Base Relocation Directory. Decrease ++ * the section's virtual size so that it equal RelocDir's ++ * idea, but only for the purposes of relocate_coff(). */ ++ grub_dprintf ("chain", ++ " section is (overlong) relocation section\n"); ++ grub_memcpy (&fake_reloc_section, section, sizeof *section); ++ fake_reloc_section.virtual_size -= (end - reloc_base_end); ++ reloc_section = &fake_reloc_section; ++ } + } +- else ++ ++ if (!reloc_section) + { + grub_dprintf ("chain", " section is not reloc section?\n"); + grub_dprintf ("chain", " rds: 0x%08x, vs: %08x\n", diff --git a/SOURCES/0229-Add-some-grub_dprintf-in-the-linuxefi-path.patch b/SOURCES/0229-Add-some-grub_dprintf-in-the-linuxefi-path.patch new file mode 100644 index 0000000..4050058 --- /dev/null +++ b/SOURCES/0229-Add-some-grub_dprintf-in-the-linuxefi-path.patch @@ -0,0 +1,85 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 9 May 2016 14:15:17 -0400 +Subject: [PATCH] Add some grub_dprintf() in the linuxefi path. + +Signed-off-by: Peter Jones +--- + grub-core/loader/efi/linux.c | 16 +++++++++++++--- + grub-core/loader/i386/efi/linux.c | 10 +++++++++- + 2 files changed, 22 insertions(+), 4 deletions(-) + +diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c +index 8890bdf059a..dbf63e20ed8 100644 +--- a/grub-core/loader/efi/linux.c ++++ b/grub-core/loader/efi/linux.c +@@ -43,12 +43,22 @@ grub_linuxefi_secure_validate (void *data, grub_uint32_t size) + shim_lock = grub_efi_locate_protocol(&guid, NULL); + grub_dprintf ("secureboot", "shim_lock: %p\n", shim_lock); + if (!shim_lock) +- return 0; ++ { ++ grub_dprintf ("secureboot", "shim not available\n"); ++ return 0; ++ } + +- status = shim_lock->verify(data, size); ++ grub_dprintf ("secureboot", "Asking shim to verify kernel signature\n"); ++ status = shim_lock->verify (data, size); + grub_dprintf ("secureboot", "shim_lock->verify(): %ld\n", status); + if (status == GRUB_EFI_SUCCESS) +- return 1; ++ { ++ grub_dprintf ("secureboot", "Kernel signature verification passed\n"); ++ return 1; ++ } ++ ++ grub_dprintf ("secureboot", "Kernel signature verification failed (0x%lx)\n", ++ (unsigned long) status); + + return -1; + } +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 010bf982d80..a95e29700c5 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -114,6 +114,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + ++ grub_dprintf ("linuxefi", "initrd_mem = %lx\n", (unsigned long) initrd_mem); ++ + params->ramdisk_size = size; + params->ramdisk_image = (grub_uint32_t)(grub_uint64_t) initrd_mem; + +@@ -202,6 +204,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + ++ grub_dprintf ("linuxefi", "params = %lx\n", (unsigned long) params); ++ + grub_memset (params, 0, 16384); + + grub_memcpy (&lh, kernel, sizeof (lh)); +@@ -239,6 +243,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + ++ grub_dprintf ("linuxefi", "linux_cmdline = %lx\n", ++ (unsigned long)linux_cmdline); ++ + grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE)); + grub_create_loader_cmdline (argc, argv, + linux_cmdline + sizeof (LINUX_IMAGE) - 1, +@@ -272,9 +279,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_memcpy (params, &lh, 2 * 512); + + params->type_of_loader = 0x21; ++ grub_dprintf("linuxefi", "kernel_mem: %p handover_offset: %08x\n", ++ kernel_mem, handover_offset); + + fail: +- + if (file) + grub_file_close (file); + diff --git a/SOURCES/0230-linuxefi-minor-cleanups.patch b/SOURCES/0230-linuxefi-minor-cleanups.patch new file mode 100644 index 0000000..b27fd18 --- /dev/null +++ b/SOURCES/0230-linuxefi-minor-cleanups.patch @@ -0,0 +1,86 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 14 Feb 2017 16:31:52 -0500 +Subject: [PATCH] linuxefi: minor cleanups + +Signed-off-by: Peter Jones +--- + grub-core/loader/i386/efi/linux.c | 30 ++++++++++++++++++++---------- + 1 file changed, 20 insertions(+), 10 deletions(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index a95e29700c5..806031838ae 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -61,13 +61,18 @@ grub_linuxefi_unload (void) + grub_dl_unref (my_mod); + loaded = 0; + if (initrd_mem) +- grub_efi_free_pages((grub_efi_physical_address_t)initrd_mem, BYTES_TO_PAGES(params->ramdisk_size)); ++ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)initrd_mem, ++ BYTES_TO_PAGES(params->ramdisk_size)); + if (linux_cmdline) +- grub_efi_free_pages((grub_efi_physical_address_t)linux_cmdline, BYTES_TO_PAGES(params->cmdline_size + 1)); ++ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t) ++ linux_cmdline, ++ BYTES_TO_PAGES(params->cmdline_size + 1)); + if (kernel_mem) +- grub_efi_free_pages((grub_efi_physical_address_t)kernel_mem, BYTES_TO_PAGES(kernel_size)); ++ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)kernel_mem, ++ BYTES_TO_PAGES(kernel_size)); + if (params) +- grub_efi_free_pages((grub_efi_physical_address_t)params, BYTES_TO_PAGES(16384)); ++ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)params, ++ BYTES_TO_PAGES(16384)); + return GRUB_ERR_NONE; + } + +@@ -117,7 +122,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + grub_dprintf ("linuxefi", "initrd_mem = %lx\n", (unsigned long) initrd_mem); + + params->ramdisk_size = size; +- params->ramdisk_image = (grub_uint32_t)(grub_uint64_t) initrd_mem; ++ params->ramdisk_image = (grub_uint32_t)(grub_addr_t) initrd_mem; + + ptr = initrd_mem; + +@@ -144,7 +149,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + grub_free (files); + + if (initrd_mem && grub_errno) +- grub_efi_free_pages((grub_efi_physical_address_t)initrd_mem, BYTES_TO_PAGES(size)); ++ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)initrd_mem, ++ BYTES_TO_PAGES(size)); + + return grub_errno; + } +@@ -251,7 +257,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + linux_cmdline + sizeof (LINUX_IMAGE) - 1, + lh.cmdline_size - (sizeof (LINUX_IMAGE) - 1)); + +- lh.cmd_line_ptr = (grub_uint32_t)(grub_uint64_t)linux_cmdline; ++ lh.cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline; + + handover_offset = lh.handover_offset; + +@@ -296,13 +302,17 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + } + + if (linux_cmdline && !loaded) +- grub_efi_free_pages((grub_efi_physical_address_t)linux_cmdline, BYTES_TO_PAGES(lh.cmdline_size + 1)); ++ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t) ++ linux_cmdline, ++ BYTES_TO_PAGES(lh.cmdline_size + 1)); + + if (kernel_mem && !loaded) +- grub_efi_free_pages((grub_efi_physical_address_t)kernel_mem, BYTES_TO_PAGES(kernel_size)); ++ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)kernel_mem, ++ BYTES_TO_PAGES(kernel_size)); + + if (params && !loaded) +- grub_efi_free_pages((grub_efi_physical_address_t)params, BYTES_TO_PAGES(16384)); ++ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)params, ++ BYTES_TO_PAGES(16384)); + + return grub_errno; + } diff --git a/SOURCES/0231-Handle-multi-arch-64-on-32-boot-in-linuxefi-loader.patch b/SOURCES/0231-Handle-multi-arch-64-on-32-boot-in-linuxefi-loader.patch new file mode 100644 index 0000000..a6b68e2 --- /dev/null +++ b/SOURCES/0231-Handle-multi-arch-64-on-32-boot-in-linuxefi-loader.patch @@ -0,0 +1,257 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 14 Feb 2017 16:18:54 -0500 +Subject: [PATCH] Handle multi-arch (64-on-32) boot in linuxefi loader. + +Allow booting 64-bit kernels on 32-bit EFI on x86. + +Signed-off-by: Peter Jones +--- + grub-core/loader/efi/linux.c | 9 +++- + grub-core/loader/i386/efi/linux.c | 105 +++++++++++++++++++++++++++----------- + include/grub/i386/linux.h | 7 ++- + 3 files changed, 87 insertions(+), 34 deletions(-) + +diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c +index dbf63e20ed8..7fe7201a388 100644 +--- a/grub-core/loader/efi/linux.c ++++ b/grub-core/loader/efi/linux.c +@@ -66,12 +66,17 @@ grub_linuxefi_secure_validate (void *data, grub_uint32_t size) + typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *); + + grub_err_t +-grub_efi_linux_boot (void *kernel_addr, grub_off_t offset, ++grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset, + void *kernel_params) + { + handover_func hf; ++ int offset = 0; + +- hf = (handover_func)((char *)kernel_addr + offset); ++#ifdef __x86_64__ ++ offset = 512; ++#endif ++ ++ hf = (handover_func)((char *)kernel_addr + handover_offset + offset); + hf (grub_efi_image_handle, grub_efi_system_table, kernel_params); + + return GRUB_ERR_BUG; +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 806031838ae..c123afad19c 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -44,14 +44,10 @@ static char *linux_cmdline; + static grub_err_t + grub_linuxefi_boot (void) + { +- int offset = 0; +- +-#ifdef __x86_64__ +- offset = 512; +-#endif + asm volatile ("cli"); + +- return grub_efi_linux_boot ((char *)kernel_mem, handover_offset + offset, ++ return grub_efi_linux_boot ((char *)kernel_mem, ++ handover_offset, + params); + } + +@@ -155,14 +151,20 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + return grub_errno; + } + ++#define MIN(a, b) \ ++ ({ typeof (a) _a = (a); \ ++ typeof (b) _b = (b); \ ++ _a < _b ? _a : _b; }) ++ + static grub_err_t + grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) + { + grub_file_t file = 0; +- struct linux_kernel_header lh; ++ struct linux_kernel_header *lh; + grub_ssize_t len, start, filelen; + void *kernel = NULL; ++ int setup_header_end_offset; + int rc; + + grub_dl_ref (my_mod); +@@ -202,47 +204,78 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + +- params = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(16384)); +- ++ params = grub_efi_allocate_pages_max (0x3fffffff, ++ BYTES_TO_PAGES(sizeof(*params))); + if (! params) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters"); + goto fail; + } + +- grub_dprintf ("linuxefi", "params = %lx\n", (unsigned long) params); ++ grub_dprintf ("linuxefi", "params = %p\n", (unsigned long) params); + +- grub_memset (params, 0, 16384); ++ grub_memset (params, 0, sizeof(*params)); + +- grub_memcpy (&lh, kernel, sizeof (lh)); +- +- if (lh.boot_flag != grub_cpu_to_le16 (0xaa55)) ++ setup_header_end_offset = *((grub_uint8_t *)kernel + 0x201); ++ grub_dprintf ("linuxefi", "copying %lu bytes from %p to %p\n", ++ MIN(0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1, ++ (grub_uint8_t *)kernel + 0x1f1, ++ (grub_uint8_t *)params + 0x1f1); ++ grub_memcpy ((grub_uint8_t *)params + 0x1f1, ++ (grub_uint8_t *)kernel + 0x1f1, ++ MIN(0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1); ++ lh = (struct linux_kernel_header *)params; ++ grub_dprintf ("linuxefi", "lh is at %p\n", lh); ++ grub_dprintf ("linuxefi", "checking lh->boot_flag\n"); ++ if (lh->boot_flag != grub_cpu_to_le16 (0xaa55)) + { + grub_error (GRUB_ERR_BAD_OS, N_("invalid magic number")); + goto fail; + } + +- if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS) ++ grub_dprintf ("linuxefi", "checking lh->setup_sects\n"); ++ if (lh->setup_sects > GRUB_LINUX_MAX_SETUP_SECTS) + { + grub_error (GRUB_ERR_BAD_OS, N_("too many setup sectors")); + goto fail; + } + +- if (lh.version < grub_cpu_to_le16 (0x020b)) ++ grub_dprintf ("linuxefi", "checking lh->version\n"); ++ if (lh->version < grub_cpu_to_le16 (0x020b)) + { + grub_error (GRUB_ERR_BAD_OS, N_("kernel too old")); + goto fail; + } + +- if (!lh.handover_offset) ++ grub_dprintf ("linuxefi", "checking lh->handover_offset\n"); ++ if (!lh->handover_offset) + { + grub_error (GRUB_ERR_BAD_OS, N_("kernel doesn't support EFI handover")); + goto fail; + } + ++#ifdef defined(__x86_64__) || defined(__aarch64__) ++ grub_dprintf ("linuxefi", "checking lh->xloadflags\n"); ++ if (!(lh->xloadflags & LINUX_XLF_KERNEL_64)) ++ { ++ grub_error (GRUB_ERR_BAD_OS, N_("kernel doesn't support 64-bit CPUs")); ++ goto fail; ++ } ++#endif ++ ++#if defined(__i386__) ++ if ((lh->xloadflags & LINUX_XLF_KERNEL_64) && ++ !(lh->xloadflags & LINUX_XLF_EFI_HANDOVER_32)) ++ { ++ grub_error (GRUB_ERR_BAD_OS, ++ N_("kernel doesn't support 32-bit handover")); ++ goto fail; ++ } ++#endif ++ ++ grub_dprintf ("linuxefi", "setting up cmdline\n"); + linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff, +- BYTES_TO_PAGES(lh.cmdline_size + 1)); +- ++ BYTES_TO_PAGES(lh->cmdline_size + 1)); + if (!linux_cmdline) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline")); +@@ -255,21 +288,24 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE)); + grub_create_loader_cmdline (argc, argv, + linux_cmdline + sizeof (LINUX_IMAGE) - 1, +- lh.cmdline_size - (sizeof (LINUX_IMAGE) - 1)); ++ lh->cmdline_size - (sizeof (LINUX_IMAGE) - 1)); + +- lh.cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline; ++ grub_dprintf ("linuxefi", "cmdline:%s\n", linux_cmdline); ++ grub_dprintf ("linuxefi", "setting lh->cmd_line_ptr\n"); ++ lh->cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline; + +- handover_offset = lh.handover_offset; ++ grub_dprintf ("linuxefi", "computing handover offset\n"); ++ handover_offset = lh->handover_offset; + +- start = (lh.setup_sects + 1) * 512; ++ start = (lh->setup_sects + 1) * 512; + len = grub_file_size(file) - start; + +- kernel_mem = grub_efi_allocate_pages(lh.pref_address, +- BYTES_TO_PAGES(lh.init_size)); ++ kernel_mem = grub_efi_allocate_pages(lh->pref_address, ++ BYTES_TO_PAGES(lh->init_size)); + + if (!kernel_mem) + kernel_mem = grub_efi_allocate_pages_max(0x3fffffff, +- BYTES_TO_PAGES(lh.init_size)); ++ BYTES_TO_PAGES(lh->init_size)); + + if (!kernel_mem) + { +@@ -277,14 +313,21 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + +- grub_memcpy (kernel_mem, (char *)kernel + start, len); ++ grub_dprintf ("linuxefi", "kernel_mem = %lx\n", (unsigned long) kernel_mem); ++ + grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0); + loaded=1; ++ grub_dprintf ("linuxefi", "setting lh->code32_start to %p\n", kernel_mem); ++ lh->code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem; + +- lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem; +- grub_memcpy (params, &lh, 2 * 512); ++ grub_memcpy (kernel_mem, (char *)kernel + start, filelen - start); + +- params->type_of_loader = 0x21; ++ grub_dprintf ("linuxefi", "setting lh->type_of_loader\n"); ++ lh->type_of_loader = 0x6; ++ ++ grub_dprintf ("linuxefi", "setting lh->ext_loader_{type,ver}\n"); ++ params->ext_loader_type = 0; ++ params->ext_loader_ver = 2; + grub_dprintf("linuxefi", "kernel_mem: %p handover_offset: %08x\n", + kernel_mem, handover_offset); + +@@ -304,7 +347,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + if (linux_cmdline && !loaded) + grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t) + linux_cmdline, +- BYTES_TO_PAGES(lh.cmdline_size + 1)); ++ BYTES_TO_PAGES(lh->cmdline_size + 1)); + + if (kernel_mem && !loaded) + grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)kernel_mem, +diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h +index fc36bdaf367..110ecf806fb 100644 +--- a/include/grub/i386/linux.h ++++ b/include/grub/i386/linux.h +@@ -130,7 +130,12 @@ struct linux_kernel_header + grub_uint32_t kernel_alignment; + grub_uint8_t relocatable; + grub_uint8_t min_alignment; +- grub_uint8_t pad[2]; ++#define LINUX_XLF_KERNEL_64 (1<<0) ++#define LINUX_XLF_CAN_BE_LOADED_ABOVE_4G (1<<1) ++#define LINUX_XLF_EFI_HANDOVER_32 (1<<2) ++#define LINUX_XLF_EFI_HANDOVER_64 (1<<3) ++#define LINUX_XLF_EFI_KEXEC (1<<4) ++ grub_uint16_t xloadflags; + grub_uint32_t cmdline_size; + grub_uint32_t hardware_subarch; + grub_uint64_t hardware_subarch_data; diff --git a/SOURCES/0232-efidisk-Respect-block_io_protocol-buffer-alignment.patch b/SOURCES/0232-efidisk-Respect-block_io_protocol-buffer-alignment.patch new file mode 100644 index 0000000..255ab30 --- /dev/null +++ b/SOURCES/0232-efidisk-Respect-block_io_protocol-buffer-alignment.patch @@ -0,0 +1,92 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Leif Lindholm +Date: Sat, 27 Feb 2016 13:44:59 +0100 +Subject: [PATCH] efidisk: Respect block_io_protocol buffer alignment + +Returned from the OpenProtocol operation, the grub_efi_block_io_media +structure contains the io_align field, specifying the minimum alignment +required for buffers used in any data transfers with the device. + +Make grub_efidisk_readwrite() allocate a temporary buffer, aligned to +this boundary, if the buffer passed to it does not already meet the +requirements. + +Also sanity check the io_align field in grub_efidisk_open() for +power-of-two-ness and bail if invalid. + +Cherry-picked-from: 51f375d688529b7c1819ba40188ee52b9333887c +Resolves: rhbz#1300009 +--- + grub-core/disk/efi/efidisk.c | 48 +++++++++++++++++++++++++++++++++++++------- + 1 file changed, 41 insertions(+), 7 deletions(-) + +diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c +index 845c66fa9ab..f04f20b84ff 100644 +--- a/grub-core/disk/efi/efidisk.c ++++ b/grub-core/disk/efi/efidisk.c +@@ -487,8 +487,15 @@ grub_efidisk_open (const char *name, struct grub_disk *disk) + m = d->block_io->media; + /* FIXME: Probably it is better to store the block size in the disk, + and total sectors should be replaced with total blocks. */ +- grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n", +- m, (unsigned long long) m->last_block, m->block_size); ++ grub_dprintf ("efidisk", ++ "m = %p, last block = %llx, block size = %x, io align = %x\n", ++ m, (unsigned long long) m->last_block, m->block_size, ++ m->io_align); ++ ++ /* Ensure required buffer alignment is a power of two (or is zero). */ ++ if (m->io_align & (m->io_align - 1)) ++ return grub_error (GRUB_ERR_IO, "invalid buffer alignment %d", m->io_align); ++ + disk->total_sectors = m->last_block + 1; + /* Don't increase this value due to bug in some EFI. */ + disk->max_agglomerate = 0xa0000 >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS); +@@ -518,15 +525,42 @@ grub_efidisk_readwrite (struct grub_disk *disk, grub_disk_addr_t sector, + { + struct grub_efidisk_data *d; + grub_efi_block_io_t *bio; ++ grub_efi_status_t status; ++ grub_size_t io_align, num_bytes; ++ char *aligned_buf; + + d = disk->data; + bio = d->block_io; + +- return efi_call_5 ((wr ? bio->write_blocks : bio->read_blocks), bio, +- bio->media->media_id, +- (grub_efi_uint64_t) sector, +- (grub_efi_uintn_t) size << disk->log_sector_size, +- buf); ++ /* Set alignment to 1 if 0 specified */ ++ io_align = bio->media->io_align ? bio->media->io_align : 1; ++ num_bytes = size << disk->log_sector_size; ++ ++ if ((grub_addr_t) buf & (io_align - 1)) ++ { ++ aligned_buf = grub_memalign (io_align, num_bytes); ++ if (! aligned_buf) ++ return GRUB_EFI_OUT_OF_RESOURCES; ++ if (wr) ++ grub_memcpy (aligned_buf, buf, num_bytes); ++ } ++ else ++ { ++ aligned_buf = buf; ++ } ++ ++ status = efi_call_5 ((wr ? bio->write_blocks : bio->read_blocks), bio, ++ bio->media->media_id, (grub_efi_uint64_t) sector, ++ (grub_efi_uintn_t) num_bytes, aligned_buf); ++ ++ if ((grub_addr_t) buf & (io_align - 1)) ++ { ++ if (!wr) ++ grub_memcpy (buf, aligned_buf, num_bytes); ++ grub_free (aligned_buf); ++ } ++ ++ return status; + } + + static grub_err_t diff --git a/SOURCES/0233-loader-linux-Make-trailer-initrd-entry-aligned-again.patch b/SOURCES/0233-loader-linux-Make-trailer-initrd-entry-aligned-again.patch new file mode 100644 index 0000000..e87d491 --- /dev/null +++ b/SOURCES/0233-loader-linux-Make-trailer-initrd-entry-aligned-again.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bernhard=20=C3=9Cbelacker?= +Date: Mon, 20 Jul 2015 14:06:45 +0200 +Subject: [PATCH] loader/linux: Make trailer initrd entry aligned again. + +Regression from commit: + loader/linux: do not pad initrd with zeroes at the end + a8c473288d3f0a5e17a903a5121dea1a695dda3b + +Wimboot fails since the change above because it expects the "trailer" +initrd element on an aligned address. +This issue shows only when newc_name is used and the last initrd +entry has a not aligned size. +--- + grub-core/loader/linux.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c +index d2cd591f604..be6fa0f4d45 100644 +--- a/grub-core/loader/linux.c ++++ b/grub-core/loader/linux.c +@@ -213,6 +213,7 @@ grub_initrd_init (int argc, char *argv[], + + if (newc) + { ++ initrd_ctx->size = ALIGN_UP (initrd_ctx->size, 4); + initrd_ctx->size += ALIGN_UP (sizeof (struct newc_head) + + sizeof ("TRAILER!!!") - 1, 4); + free_dir (root); +@@ -290,7 +291,11 @@ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx, + ptr += cursize; + } + if (newc) +- ptr = make_header (ptr, "TRAILER!!!", sizeof ("TRAILER!!!") - 1, 0, 0); ++ { ++ grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4)); ++ ptr += ALIGN_UP_OVERHEAD (cursize, 4); ++ ptr = make_header (ptr, "TRAILER!!!", sizeof ("TRAILER!!!") - 1, 0, 0); ++ } + free_dir (root); + root = 0; + return GRUB_ERR_NONE; diff --git a/SOURCES/0234-Make-exit-take-a-return-code.patch b/SOURCES/0234-Make-exit-take-a-return-code.patch new file mode 100644 index 0000000..6eca76a --- /dev/null +++ b/SOURCES/0234-Make-exit-take-a-return-code.patch @@ -0,0 +1,260 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 26 Feb 2014 21:49:12 -0500 +Subject: [PATCH] Make "exit" take a return code. + +This adds "exit" with a return code. With this patch, any "exit" +command /may/ include a return code, and on platforms that support +returning with an exit status, we will do so. By default we return the +same exit status we did before this patch. + +Signed-off-by: Peter Jones +--- + grub-core/commands/minicmd.c | 20 ++++++++++++++++---- + grub-core/kern/efi/efi.c | 9 +++++++-- + grub-core/kern/emu/main.c | 6 ++++++ + grub-core/kern/emu/misc.c | 5 +++-- + grub-core/kern/i386/coreboot/init.c | 2 +- + grub-core/kern/i386/qemu/init.c | 2 +- + grub-core/kern/ieee1275/init.c | 2 +- + grub-core/kern/mips/arc/init.c | 2 +- + grub-core/kern/mips/loongson/init.c | 2 +- + grub-core/kern/mips/qemu_mips/init.c | 2 +- + grub-core/kern/misc.c | 2 +- + grub-core/kern/uboot/init.c | 6 +++--- + grub-core/kern/xen/init.c | 2 +- + include/grub/misc.h | 2 +- + 14 files changed, 44 insertions(+), 20 deletions(-) + +diff --git a/grub-core/commands/minicmd.c b/grub-core/commands/minicmd.c +index a3a11824172..b25ca4b9f17 100644 +--- a/grub-core/commands/minicmd.c ++++ b/grub-core/commands/minicmd.c +@@ -176,12 +176,24 @@ grub_mini_cmd_lsmod (struct grub_command *cmd __attribute__ ((unused)), + } + + /* exit */ +-static grub_err_t __attribute__ ((noreturn)) ++static grub_err_t + grub_mini_cmd_exit (struct grub_command *cmd __attribute__ ((unused)), +- int argc __attribute__ ((unused)), +- char *argv[] __attribute__ ((unused))) ++ int argc, char *argv[]) + { +- grub_exit (); ++ int retval = -1; ++ unsigned long n; ++ ++ if (argc < 0 || argc > 1) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); ++ ++ if (argc == 1) ++ { ++ n = grub_strtoul (argv[0], 0, 10); ++ if (n != ~0UL) ++ retval = n; ++ } ++ ++ grub_exit (retval); + /* Not reached. */ + } + +diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c +index 7dfe2ef1455..453f97a7595 100644 +--- a/grub-core/kern/efi/efi.c ++++ b/grub-core/kern/efi/efi.c +@@ -155,11 +155,16 @@ grub_efi_get_loaded_image (grub_efi_handle_t image_handle) + } + + void +-grub_exit (void) ++grub_exit (int retval) + { ++ int rc = GRUB_EFI_LOAD_ERROR; ++ ++ if (retval == 0) ++ rc = GRUB_EFI_SUCCESS; ++ + grub_machine_fini (GRUB_LOADER_FLAG_NORETURN); + efi_call_4 (grub_efi_system_table->boot_services->exit, +- grub_efi_image_handle, GRUB_EFI_LOAD_ERROR, 0, 0); ++ grub_efi_image_handle, rc, 0, 0); + for (;;) ; + } + +diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c +index 4b509139c4a..d7c880c0c1f 100644 +--- a/grub-core/kern/emu/main.c ++++ b/grub-core/kern/emu/main.c +@@ -65,6 +65,12 @@ grub_reboot (void) + longjmp (main_env, 1); + } + ++void ++grub_exit (int retval __attribute__((unused))) ++{ ++ grub_reboot (); ++} ++ + void + grub_machine_init (void) + { +diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c +index bb606da2803..258a5649e2d 100644 +--- a/grub-core/kern/emu/misc.c ++++ b/grub-core/kern/emu/misc.c +@@ -135,9 +135,10 @@ xasprintf (const char *fmt, ...) + #endif + + void +-grub_exit (void) ++__attribute__ ((noreturn)) ++grub_exit (int rc) + { +- exit (1); ++ exit (rc < 0 ? 1 : rc); + } + + grub_uint64_t +diff --git a/grub-core/kern/i386/coreboot/init.c b/grub-core/kern/i386/coreboot/init.c +index 3314f027fec..36f9134b7b7 100644 +--- a/grub-core/kern/i386/coreboot/init.c ++++ b/grub-core/kern/i386/coreboot/init.c +@@ -41,7 +41,7 @@ extern grub_uint8_t _end[]; + extern grub_uint8_t _edata[]; + + void __attribute__ ((noreturn)) +-grub_exit (void) ++grub_exit (int rc __attribute__((unused))) + { + /* We can't use grub_fatal() in this function. This would create an infinite + loop, since grub_fatal() calls grub_abort() which in turn calls grub_exit(). */ +diff --git a/grub-core/kern/i386/qemu/init.c b/grub-core/kern/i386/qemu/init.c +index 271b6fbfabd..9fafe98f015 100644 +--- a/grub-core/kern/i386/qemu/init.c ++++ b/grub-core/kern/i386/qemu/init.c +@@ -42,7 +42,7 @@ extern grub_uint8_t _end[]; + extern grub_uint8_t _edata[]; + + void __attribute__ ((noreturn)) +-grub_exit (void) ++grub_exit (int rc __attribute__((unused))) + { + /* We can't use grub_fatal() in this function. This would create an infinite + loop, since grub_fatal() calls grub_abort() which in turn calls grub_exit(). */ +diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c +index 8ca4bf79f09..e2540bc41ce 100644 +--- a/grub-core/kern/ieee1275/init.c ++++ b/grub-core/kern/ieee1275/init.c +@@ -60,7 +60,7 @@ grub_addr_t grub_ieee1275_original_stack; + #endif + + void +-grub_exit (void) ++grub_exit (int rc __attribute__((unused))) + { + grub_ieee1275_exit (); + } +diff --git a/grub-core/kern/mips/arc/init.c b/grub-core/kern/mips/arc/init.c +index b4f50e49642..90049cb53ce 100644 +--- a/grub-core/kern/mips/arc/init.c ++++ b/grub-core/kern/mips/arc/init.c +@@ -276,7 +276,7 @@ grub_halt (void) + } + + void +-grub_exit (void) ++grub_exit (int rc __attribute__((unused))) + { + GRUB_ARC_FIRMWARE_VECTOR->exit (); + +diff --git a/grub-core/kern/mips/loongson/init.c b/grub-core/kern/mips/loongson/init.c +index 7b96531b983..dff598ca7b0 100644 +--- a/grub-core/kern/mips/loongson/init.c ++++ b/grub-core/kern/mips/loongson/init.c +@@ -304,7 +304,7 @@ grub_halt (void) + } + + void +-grub_exit (void) ++grub_exit (int rc __attribute__((unused))) + { + grub_halt (); + } +diff --git a/grub-core/kern/mips/qemu_mips/init.c b/grub-core/kern/mips/qemu_mips/init.c +index be88b77d22d..8b6c55ffc01 100644 +--- a/grub-core/kern/mips/qemu_mips/init.c ++++ b/grub-core/kern/mips/qemu_mips/init.c +@@ -75,7 +75,7 @@ grub_machine_fini (int flags __attribute__ ((unused))) + } + + void +-grub_exit (void) ++grub_exit (int rc __attribute__((unused))) + { + grub_halt (); + } +diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c +index 392c697db03..240396c55f3 100644 +--- a/grub-core/kern/misc.c ++++ b/grub-core/kern/misc.c +@@ -1278,7 +1278,7 @@ grub_abort (void) + grub_getkey (); + } + +- grub_exit (); ++ grub_exit (1); + } + + #if defined (__clang__) && !defined (GRUB_UTIL) +diff --git a/grub-core/kern/uboot/init.c b/grub-core/kern/uboot/init.c +index 5dcc106ed9b..430c62b66e0 100644 +--- a/grub-core/kern/uboot/init.c ++++ b/grub-core/kern/uboot/init.c +@@ -43,9 +43,9 @@ extern grub_uint32_t grub_uboot_machine_type; + extern grub_addr_t grub_uboot_boot_data; + + void +-grub_exit (void) ++grub_exit (int rc) + { +- grub_uboot_return (0); ++ grub_uboot_return (rc < 0 ? 1 : rc); + } + + grub_uint32_t +@@ -94,7 +94,7 @@ grub_machine_init (void) + if (!ver) + { + /* Don't even have a console to log errors to... */ +- grub_exit (); ++ grub_exit (-1); + } + else if (ver > API_SIG_VERSION) + { +diff --git a/grub-core/kern/xen/init.c b/grub-core/kern/xen/init.c +index 0559c033c3d..fce526d417b 100644 +--- a/grub-core/kern/xen/init.c ++++ b/grub-core/kern/xen/init.c +@@ -549,7 +549,7 @@ grub_machine_init (void) + } + + void +-grub_exit (void) ++grub_exit (int rc __attribute__((unused))) + { + struct sched_shutdown arg; + +diff --git a/include/grub/misc.h b/include/grub/misc.h +index 34250291908..c6851fb9dcf 100644 +--- a/include/grub/misc.h ++++ b/include/grub/misc.h +@@ -398,7 +398,7 @@ int EXPORT_FUNC(grub_vsnprintf) (char *str, grub_size_t n, const char *fmt, + char *EXPORT_FUNC(grub_xasprintf) (const char *fmt, ...) + __attribute__ ((format (GNU_PRINTF, 1, 2))) WARN_UNUSED_RESULT; + char *EXPORT_FUNC(grub_xvasprintf) (const char *fmt, va_list args) WARN_UNUSED_RESULT; +-void EXPORT_FUNC(grub_exit) (void) __attribute__ ((noreturn)); ++void EXPORT_FUNC(grub_exit) (int rc) __attribute__ ((noreturn)); + grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n, + grub_uint64_t d, + grub_uint64_t *r); diff --git a/SOURCES/0235-efi-fix-memory-leak-in-variable-handling.patch b/SOURCES/0235-efi-fix-memory-leak-in-variable-handling.patch new file mode 100644 index 0000000..7985372 --- /dev/null +++ b/SOURCES/0235-efi-fix-memory-leak-in-variable-handling.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ignat Korchagin +Date: Thu, 23 Jul 2015 21:13:09 +0300 +Subject: [PATCH] efi: fix memory leak in variable handling + +--- + grub-core/kern/efi/efi.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c +index 453f97a7595..0cd64cdb59e 100644 +--- a/grub-core/kern/efi/efi.c ++++ b/grub-core/kern/efi/efi.c +@@ -211,6 +211,7 @@ grub_efi_set_variable(const char *var, const grub_efi_guid_t *guid, + | GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS + | GRUB_EFI_VARIABLE_RUNTIME_ACCESS), + datasize, data); ++ grub_free (var16); + if (status == GRUB_EFI_SUCCESS) + return GRUB_ERR_NONE; + +@@ -242,8 +243,11 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid, + + status = efi_call_5 (r->get_variable, var16, guid, NULL, &datasize, NULL); + +- if (!datasize) +- return NULL; ++ if (status != GRUB_EFI_SUCCESS || !datasize) ++ { ++ grub_free (var16); ++ return NULL; ++ } + + data = grub_malloc (datasize); + if (!data) diff --git a/SOURCES/0236-efi-fix-GetVariable-return-status-check-in-81ca24a.patch b/SOURCES/0236-efi-fix-GetVariable-return-status-check-in-81ca24a.patch new file mode 100644 index 0000000..786f17a --- /dev/null +++ b/SOURCES/0236-efi-fix-GetVariable-return-status-check-in-81ca24a.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ignat Korchagin +Date: Fri, 24 Jul 2015 20:46:02 +0300 +Subject: [PATCH] efi: fix GetVariable return status check in 81ca24a + +GetVariable should return EFI_BUFFER_TOO_SMALL if given buffer of size +zero; commit incorrectly checked for EFI_SUCCESS. +--- + grub-core/kern/efi/efi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c +index 0cd64cdb59e..101307fc71e 100644 +--- a/grub-core/kern/efi/efi.c ++++ b/grub-core/kern/efi/efi.c +@@ -243,7 +243,7 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid, + + status = efi_call_5 (r->get_variable, var16, guid, NULL, &datasize, NULL); + +- if (status != GRUB_EFI_SUCCESS || !datasize) ++ if (status != GRUB_EFI_BUFFER_TOO_SMALL || !datasize) + { + grub_free (var16); + return NULL; diff --git a/SOURCES/0237-linux.c-Ensure-that-initrd-is-page-aligned.patch b/SOURCES/0237-linux.c-Ensure-that-initrd-is-page-aligned.patch new file mode 100644 index 0000000..ab1325c --- /dev/null +++ b/SOURCES/0237-linux.c-Ensure-that-initrd-is-page-aligned.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Thu, 7 May 2015 16:23:39 +0200 +Subject: [PATCH] linux.c: Ensure that initrd is page-aligned. + +--- + grub-core/loader/i386/linux.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c +index 53f74ae0685..764cde20318 100644 +--- a/grub-core/loader/i386/linux.c ++++ b/grub-core/loader/i386/linux.c +@@ -70,7 +70,6 @@ static grub_addr_t prot_mode_target; + static void *initrd_mem; + static grub_addr_t initrd_mem_target; + static grub_size_t prot_init_space; +-static grub_uint32_t initrd_pages; + static struct grub_relocator *relocator = NULL; + static void *efi_mmap_buf; + static grub_size_t maximal_cmdline_size; +@@ -1055,7 +1054,7 @@ static grub_err_t + grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) + { +- grub_size_t size = 0; ++ grub_size_t size = 0, aligned_size = 0; + grub_addr_t addr_min, addr_max; + grub_addr_t addr; + grub_err_t err; +@@ -1077,8 +1076,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + goto fail; + + size = grub_get_initrd_size (&initrd_ctx); +- +- initrd_pages = (page_align (size) >> 12); ++ aligned_size = ALIGN_UP (size, 4096); + + /* Get the highest address available for the initrd. */ + if (grub_le_to_cpu16 (linux_params.version) >= 0x0203) +@@ -1106,7 +1104,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + addr_min = (grub_addr_t) prot_mode_target + prot_init_space; + + /* Put the initrd as high as possible, 4KiB aligned. */ +- addr = (addr_max - size) & ~0xFFF; ++ addr = (addr_max - aligned_size) & ~0xFFF; + + if (addr < addr_min) + { +@@ -1117,7 +1115,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_align (relocator, &ch, +- addr_min, addr, size, 0x1000, ++ addr_min, addr, aligned_size, ++ 0x1000, + GRUB_RELOCATOR_PREFERENCE_HIGH, + 1); + if (err) diff --git a/SOURCES/0238-arm64-make-sure-fdt-has-address-cells-and-size-cells.patch b/SOURCES/0238-arm64-make-sure-fdt-has-address-cells-and-size-cells.patch new file mode 100644 index 0000000..0511a41 --- /dev/null +++ b/SOURCES/0238-arm64-make-sure-fdt-has-address-cells-and-size-cells.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Salter +Date: Mon, 17 Apr 2017 08:44:29 -0400 +Subject: [PATCH] arm64: make sure fdt has #address-cells and #size-cells + properties + +Recent upstream changes to kexec-tools relies on #address-cells +and #size-cells properties in the FDT. If grub2 needs to create +a chosen node, it is likely because firmware did not provide one. +In that case, set #address-cells and #size-cells properties to +make sure they exist. +--- + grub-core/loader/arm64/linux.c | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c +index 0452a20e98b..1eb332a892c 100644 +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -147,7 +147,21 @@ finalize_params (void) + + node = grub_fdt_find_subnode (fdt, 0, "chosen"); + if (node < 0) +- node = grub_fdt_add_subnode (fdt, 0, "chosen"); ++ { ++ /* ++ * If we have to create a chosen node, Make sure we ++ * have #address-cells and #size-cells properties. ++ */ ++ retval = grub_fdt_set_prop32(fdt, 0, "#address-cells", 2); ++ if (retval) ++ goto failure; ++ ++ retval = grub_fdt_set_prop32(fdt, 0, "#size-cells", 2); ++ if (retval) ++ goto failure; ++ ++ node = grub_fdt_add_subnode (fdt, 0, "chosen"); ++ } + + if (node < 1) + goto failure; diff --git a/SOURCES/0239-Don-t-guess-boot-efi-as-on-ppc-machines.patch b/SOURCES/0239-Don-t-guess-boot-efi-as-on-ppc-machines.patch new file mode 100644 index 0000000..88e421e --- /dev/null +++ b/SOURCES/0239-Don-t-guess-boot-efi-as-on-ppc-machines.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 20 Apr 2017 13:29:06 -0400 +Subject: [PATCH] Don't guess /boot/efi/ as on ppc machines + +This should never be trying this, and since we've consolidated the +grubenv to always be on /boot/efi/EFI/redhat/, this code causes it to +always make the wrong decision. + +Resolves: rhbz#1443809 + +Signed-off-by: Peter Jones +--- + util/grub-install.c | 12 +----------- + 1 file changed, 1 insertion(+), 11 deletions(-) + +diff --git a/util/grub-install.c b/util/grub-install.c +index 7d61c32be2f..947a2d2ddf5 100644 +--- a/util/grub-install.c ++++ b/util/grub-install.c +@@ -1151,18 +1151,8 @@ main (int argc, char *argv[]) + char *d; + + is_guess = 1; +- d = grub_util_path_concat (2, bootdir, "macppc"); +- if (!grub_util_is_directory (d)) +- { +- free (d); +- d = grub_util_path_concat (2, bootdir, "efi"); +- } + /* Find the Mac HFS(+) System Partition. */ +- if (!grub_util_is_directory (d)) +- { +- free (d); +- d = grub_util_path_concat (2, bootdir, "EFI"); +- } ++ d = grub_util_path_concat (2, bootdir, "macppc"); + if (!grub_util_is_directory (d)) + { + free (d); diff --git a/SOURCES/0240-Clean-up-some-errors-in-the-linuxefi-loader.patch b/SOURCES/0240-Clean-up-some-errors-in-the-linuxefi-loader.patch new file mode 100644 index 0000000..d793767 --- /dev/null +++ b/SOURCES/0240-Clean-up-some-errors-in-the-linuxefi-loader.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 24 May 2017 15:58:18 -0400 +Subject: [PATCH] Clean up some errors in the linuxefi loader + +Signed-off-by: Peter Jones +--- + grub-core/loader/i386/efi/linux.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index c123afad19c..7166ec17f8f 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -161,8 +161,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) + { + grub_file_t file = 0; +- struct linux_kernel_header *lh; +- grub_ssize_t len, start, filelen; ++ struct linux_kernel_header *lh = NULL; ++ grub_ssize_t start, filelen; + void *kernel = NULL; + int setup_header_end_offset; + int rc; +@@ -212,18 +212,19 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + +- grub_dprintf ("linuxefi", "params = %p\n", (unsigned long) params); ++ grub_dprintf ("linuxefi", "params = %p\n", params); + + grub_memset (params, 0, sizeof(*params)); + + setup_header_end_offset = *((grub_uint8_t *)kernel + 0x201); + grub_dprintf ("linuxefi", "copying %lu bytes from %p to %p\n", +- MIN(0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1, ++ MIN((grub_size_t)0x202+setup_header_end_offset, ++ sizeof (*params)) - 0x1f1, + (grub_uint8_t *)kernel + 0x1f1, + (grub_uint8_t *)params + 0x1f1); + grub_memcpy ((grub_uint8_t *)params + 0x1f1, + (grub_uint8_t *)kernel + 0x1f1, +- MIN(0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1); ++ MIN((grub_size_t)0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1); + lh = (struct linux_kernel_header *)params; + grub_dprintf ("linuxefi", "lh is at %p\n", lh); + grub_dprintf ("linuxefi", "checking lh->boot_flag\n"); +@@ -254,7 +255,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + +-#ifdef defined(__x86_64__) || defined(__aarch64__) ++#if defined(__x86_64__) || defined(__aarch64__) + grub_dprintf ("linuxefi", "checking lh->xloadflags\n"); + if (!(lh->xloadflags & LINUX_XLF_KERNEL_64)) + { +@@ -298,7 +299,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + handover_offset = lh->handover_offset; + + start = (lh->setup_sects + 1) * 512; +- len = grub_file_size(file) - start; + + kernel_mem = grub_efi_allocate_pages(lh->pref_address, + BYTES_TO_PAGES(lh->init_size)); +@@ -344,7 +344,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + loaded = 0; + } + +- if (linux_cmdline && !loaded) ++ if (linux_cmdline && lh && !loaded) + grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t) + linux_cmdline, + BYTES_TO_PAGES(lh->cmdline_size + 1)); diff --git a/SOURCES/0241-Revert-trim-arp-packets-with-abnormal-size.patch b/SOURCES/0241-Revert-trim-arp-packets-with-abnormal-size.patch new file mode 100644 index 0000000..53e9303 --- /dev/null +++ b/SOURCES/0241-Revert-trim-arp-packets-with-abnormal-size.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 18 May 2017 14:25:45 -0400 +Subject: [PATCH] Revert "trim arp packets with abnormal size" + +This reverts commit d11b2eb425d2125f67dd8d8e9b11d9be7d6f3f11. +--- + grub-core/net/arp.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c +index 77581f4b29a..d62d0cc1e01 100644 +--- a/grub-core/net/arp.c ++++ b/grub-core/net/arp.c +@@ -162,12 +162,6 @@ grub_net_arp_receive (struct grub_net_buff *nb, + if (grub_net_addr_cmp (&inf->address, &target_addr) == 0 + && grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST) + { +- if ((nb->tail - nb->data) > 50) +- { +- grub_dprintf ("net", "arp packet with abnormal size (%ld bytes).\n", +- nb->tail - nb->data); +- nb->tail = nb->data + 50; +- } + grub_net_link_level_address_t target; + /* We've already checked that pln is either 4 or 16. */ + char tmp[16]; diff --git a/SOURCES/0242-cleanup-grub_cpu_to_XXX_compile_time-for-constants.patch b/SOURCES/0242-cleanup-grub_cpu_to_XXX_compile_time-for-constants.patch new file mode 100644 index 0000000..dbaa347 --- /dev/null +++ b/SOURCES/0242-cleanup-grub_cpu_to_XXX_compile_time-for-constants.patch @@ -0,0 +1,727 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrey Borzenkov +Date: Mon, 22 Sep 2014 20:47:10 +0400 +Subject: [PATCH] cleanup: grub_cpu_to_XXX_compile_time for constants + +This tries to catch all cases where grub_cpu_to_XXX was used for constant +expressions (including sizeof). +--- + grub-core/bus/usb/ehci.c | 44 ++++++++++++++++++++-------------------- + grub-core/bus/usb/ohci.c | 8 ++++---- + grub-core/commands/gptsync.c | 6 +++--- + grub-core/disk/mdraid_linux.c | 12 +++++------ + grub-core/disk/scsi.c | 2 +- + grub-core/disk/usbms.c | 4 ++-- + grub-core/fs/hfs.c | 2 +- + grub-core/fs/reiserfs.c | 12 +++++------ + grub-core/lib/fdt.c | 12 +++++------ + grub-core/loader/i386/linux.c | 2 +- + grub-core/loader/i386/pc/linux.c | 12 +++++------ + grub-core/loader/i386/xen_file.c | 4 ++-- + grub-core/net/arp.c | 4 ++-- + grub-core/net/bootp.c | 4 ++-- + grub-core/net/ip.c | 2 +- + grub-core/net/net.c | 2 +- + grub-core/net/tftp.c | 8 ++++---- + grub-core/partmap/acorn.c | 4 ++-- + grub-core/partmap/bsdlabel.c | 2 +- + grub-core/partmap/gpt.c | 2 +- + grub-core/partmap/msdos.c | 4 ++-- + grub-core/tests/video_checksum.c | 6 +++--- + util/grub-mkfont.c | 4 ++-- + util/grub-mklayout.c | 2 +- + util/mkimage.c | 15 +++++++------- + 25 files changed, 90 insertions(+), 89 deletions(-) + +diff --git a/grub-core/bus/usb/ehci.c b/grub-core/bus/usb/ehci.c +index c0feefafe4a..8ece40086ec 100644 +--- a/grub-core/bus/usb/ehci.c ++++ b/grub-core/bus/usb/ehci.c +@@ -670,23 +670,23 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, + for (i = 0; i < (GRUB_EHCI_N_TD - 1); i++) + { + e->td_virt[i].link_td = e->td_phys + (i + 1) * sizeof (struct grub_ehci_td); +- e->td_virt[i].next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); +- e->td_virt[i].alt_next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); ++ e->td_virt[i].next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); ++ e->td_virt[i].alt_next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); + } + e->td_virt[GRUB_EHCI_N_TD - 1].next_td = +- grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); ++ grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); + e->td_virt[GRUB_EHCI_N_TD - 1].alt_next_td = +- grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); ++ grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); + e->tdfree_virt = e->td_virt; + /* Set Terminate in first QH, which is used in framelist */ +- e->qh_virt[0].qh_hptr = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE | GRUB_EHCI_HPTR_TYPE_QH); +- e->qh_virt[0].td_overlay.next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); ++ e->qh_virt[0].qh_hptr = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE | GRUB_EHCI_HPTR_TYPE_QH); ++ e->qh_virt[0].td_overlay.next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); + e->qh_virt[0].td_overlay.alt_next_td = +- grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); ++ grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); + /* Also set Halted bit in token */ +- e->qh_virt[0].td_overlay.token = grub_cpu_to_le32 (GRUB_EHCI_STATUS_HALTED); ++ e->qh_virt[0].td_overlay.token = grub_cpu_to_le32_compile_time (GRUB_EHCI_STATUS_HALTED); + /* Set the H bit in first QH used for AL */ +- e->qh_virt[1].ep_char = grub_cpu_to_le32 (GRUB_EHCI_H); ++ e->qh_virt[1].ep_char = grub_cpu_to_le32_compile_time (GRUB_EHCI_H); + /* Set Terminate into TD in rest of QHs and set horizontal link + * pointer to itself - these QHs will be used for asynchronous + * schedule and they should have valid value in horiz. link */ +@@ -697,12 +697,12 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, + e->qh_chunk) & + GRUB_EHCI_POINTER_MASK) | GRUB_EHCI_HPTR_TYPE_QH); + e->qh_virt[i].td_overlay.next_td = +- grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); ++ grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); + e->qh_virt[i].td_overlay.alt_next_td = +- grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); ++ grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); + /* Also set Halted bit in token */ + e->qh_virt[i].td_overlay.token = +- grub_cpu_to_le32 (GRUB_EHCI_STATUS_HALTED); ++ grub_cpu_to_le32_compile_time (GRUB_EHCI_STATUS_HALTED); + } + + /* Note: QH 0 and QH 1 are reserved and must not be used anywhere. +@@ -991,7 +991,7 @@ grub_ehci_find_qh (struct grub_ehci *e, grub_usb_transfer_t transfer) + target = ((transfer->endpoint << GRUB_EHCI_EP_NUM_OFF) | + transfer->devaddr) & GRUB_EHCI_TARGET_MASK; + target = grub_cpu_to_le32 (target); +- mask = grub_cpu_to_le32 (GRUB_EHCI_TARGET_MASK); ++ mask = grub_cpu_to_le32_compile_time (GRUB_EHCI_TARGET_MASK); + + /* low speed interrupt transfers are linked to the periodic */ + /* schedule, everything else to the asynchronous schedule */ +@@ -1200,7 +1200,7 @@ grub_ehci_transaction (struct grub_ehci *e, + grub_memset ((void *) td, 0, sizeof (struct grub_ehci_td)); + + /* Don't point to any TD yet, just terminate. */ +- td->next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); ++ td->next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); + /* Set alternate pointer. When short packet occurs, alternate TD + * will not be really fetched because it is not active. But don't + * forget, EHCI will try to fetch alternate TD every scan of AL +@@ -1325,9 +1325,9 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev, + /* Fill whole alternate TD by zeros (= inactive) and set + * Terminate bits and Halt bit */ + grub_memset ((void *) cdata->td_alt_virt, 0, sizeof (struct grub_ehci_td)); +- cdata->td_alt_virt->next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); +- cdata->td_alt_virt->alt_next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); +- cdata->td_alt_virt->token = grub_cpu_to_le32 (GRUB_EHCI_STATUS_HALTED); ++ cdata->td_alt_virt->next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); ++ cdata->td_alt_virt->alt_next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); ++ cdata->td_alt_virt->token = grub_cpu_to_le32_compile_time (GRUB_EHCI_STATUS_HALTED); + + /* Allocate appropriate number of TDs and set */ + for (i = 0; i < transfer->transcnt; i++) +@@ -1364,7 +1364,7 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev, + cdata->td_last_virt = td; + cdata->td_last_phys = grub_dma_virt2phys (td, e->td_chunk); + /* Last TD should not have set alternate TD */ +- cdata->td_last_virt->alt_next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); ++ cdata->td_last_virt->alt_next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); + + grub_dprintf ("ehci", "setup_transfer: cdata=%p, qh=%p\n", + cdata,cdata->qh_virt); +@@ -1377,14 +1377,14 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev, + /* Start transfer: */ + /* Unlink possible alternate pointer in QH */ + cdata->qh_virt->td_overlay.alt_next_td = +- grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); ++ grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); + /* Link new TDs with QH via next_td */ + cdata->qh_virt->td_overlay.next_td = + grub_cpu_to_le32 (grub_dma_virt2phys + (cdata->td_first_virt, e->td_chunk)); + /* Reset Active and Halted bits in QH to activate Advance Queue, + * i.e. reset token */ +- cdata->qh_virt->td_overlay.token = grub_cpu_to_le32 (0); ++ cdata->qh_virt->td_overlay.token = grub_cpu_to_le32_compile_time (0); + + /* Finito */ + transfer->controller_data = cdata; +@@ -1408,9 +1408,9 @@ grub_ehci_pre_finish_transfer (grub_usb_transfer_t transfer) + * safely manipulate with QH TD part. */ + cdata->qh_virt->td_overlay.token = (cdata->qh_virt->td_overlay.token + | +- grub_cpu_to_le32 ++ grub_cpu_to_le32_compile_time + (GRUB_EHCI_STATUS_HALTED)) & +- grub_cpu_to_le32 (~GRUB_EHCI_STATUS_ACTIVE); ++ grub_cpu_to_le32_compile_time (~GRUB_EHCI_STATUS_ACTIVE); + + /* Print debug data here if necessary */ + +diff --git a/grub-core/bus/usb/ohci.c b/grub-core/bus/usb/ohci.c +index 946a4ed7d5b..d27bfe7fb9d 100644 +--- a/grub-core/bus/usb/ohci.c ++++ b/grub-core/bus/usb/ohci.c +@@ -314,7 +314,7 @@ grub_ohci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, + grub_memset ((void *) o->ed_ctrl, 0, sizeof (struct grub_ohci_ed) + * GRUB_OHCI_CTRL_EDS); + for (j=0; j < GRUB_OHCI_CTRL_EDS; j++) +- o->ed_ctrl[j].target = grub_cpu_to_le32 (1 << 14); /* skip */ ++ o->ed_ctrl[j].target = grub_cpu_to_le32_compile_time (1 << 14); /* skip */ + + grub_dprintf ("ohci", "EDs-C: chunk=%p, virt=%p, phys=0x%02x\n", + o->ed_ctrl_chunk, o->ed_ctrl, o->ed_ctrl_addr); +@@ -329,7 +329,7 @@ grub_ohci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, + /* Preset EDs */ + grub_memset ((void*)o->ed_bulk, 0, sizeof(struct grub_ohci_ed) * GRUB_OHCI_BULK_EDS); + for (j=0; j < GRUB_OHCI_BULK_EDS; j++) +- o->ed_bulk[j].target = grub_cpu_to_le32 (1 << 14); /* skip */ ++ o->ed_bulk[j].target = grub_cpu_to_le32_compile_time (1 << 14); /* skip */ + + grub_dprintf ("ohci", "EDs-B: chunk=%p, virt=%p, phys=0x%02x\n", + o->ed_bulk_chunk, o->ed_bulk, o->ed_bulk_addr); +@@ -1349,10 +1349,10 @@ grub_ohci_fini_hw (int noreturn __attribute__ ((unused))) + /* Set skip in all EDs */ + if (o->ed_bulk) + for (i=0; i < GRUB_OHCI_BULK_EDS; i++) +- o->ed_bulk[i].target |= grub_cpu_to_le32 (1 << 14); /* skip */ ++ o->ed_bulk[i].target |= grub_cpu_to_le32_compile_time (1 << 14); /* skip */ + if (o->ed_ctrl) + for (i=0; i < GRUB_OHCI_CTRL_EDS; i++) +- o->ed_ctrl[i].target |= grub_cpu_to_le32 (1 << 14); /* skip */ ++ o->ed_ctrl[i].target |= grub_cpu_to_le32_compile_time (1 << 14); /* skip */ + + /* We should wait for next SOF to be sure that all EDs are + * unaccessed by OHCI. But OHCI can be non-functional, so +diff --git a/grub-core/commands/gptsync.c b/grub-core/commands/gptsync.c +index 3db62887b92..16592e9bbe8 100644 +--- a/grub-core/commands/gptsync.c ++++ b/grub-core/commands/gptsync.c +@@ -101,7 +101,7 @@ grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)), + } + + /* Check if it is valid. */ +- if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE)) ++ if (mbr.signature != grub_cpu_to_le16_compile_time (GRUB_PC_PARTITION_SIGNATURE)) + { + grub_device_close (dev); + return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature"); +@@ -216,7 +216,7 @@ grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)), + first_sector--; + mbr.entries[0].flag = 0; + mbr.entries[0].type = GRUB_PC_PARTITION_TYPE_GPT_DISK; +- mbr.entries[0].start = grub_cpu_to_le32 (1); ++ mbr.entries[0].start = grub_cpu_to_le32_compile_time (1); + lba_to_chs (1, + &(mbr.entries[0].start_sector), + &(mbr.entries[0].start_cylinder), +@@ -227,7 +227,7 @@ grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)), + &(mbr.entries[0].end_head)); + mbr.entries[0].length = grub_cpu_to_le32 (first_sector); + +- mbr.signature = grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE); ++ mbr.signature = grub_cpu_to_le16_compile_time (GRUB_PC_PARTITION_SIGNATURE); + + if (grub_disk_write (dev->disk, 0, 0, sizeof (mbr), &mbr)) + { +diff --git a/grub-core/disk/mdraid_linux.c b/grub-core/disk/mdraid_linux.c +index 4aa5882352e..11024ae31e0 100644 +--- a/grub-core/disk/mdraid_linux.c ++++ b/grub-core/disk/mdraid_linux.c +@@ -33,16 +33,16 @@ GRUB_MOD_LICENSE ("GPLv3+"); + #define grub_md_to_cpu64 grub_be_to_cpu64 + #define grub_md_to_cpu32 grub_be_to_cpu32 + #define grub_md_to_cpu16 grub_be_to_cpu16 +-#define grub_cpu_to_md64_compile_time grub_cpu_to_be64 +-#define grub_cpu_to_md32_compile_time grub_cpu_to_be32 +-#define grub_cpu_to_md16_compile_time grub_cpu_to_be16 ++#define grub_cpu_to_md64_compile_time grub_cpu_to_be64_compile_time ++#define grub_cpu_to_md32_compile_time grub_cpu_to_be32_compile_time ++#define grub_cpu_to_md16_compile_time grub_cpu_to_be16_compile_time + #else + #define grub_md_to_cpu64 grub_le_to_cpu64 + #define grub_md_to_cpu32 grub_le_to_cpu32 + #define grub_md_to_cpu16 grub_le_to_cpu16 +-#define grub_cpu_to_md64_compile_time grub_cpu_to_le64 +-#define grub_cpu_to_md32_compile_time grub_cpu_to_le32 +-#define grub_cpu_to_md16_compile_time grub_cpu_to_le16 ++#define grub_cpu_to_md64_compile_time grub_cpu_to_le64_compile_time ++#define grub_cpu_to_md32_compile_time grub_cpu_to_le32_compile_time ++#define grub_cpu_to_md16_compile_time grub_cpu_to_le16_compile_time + #endif + + #define RESERVED_BYTES (64 * 1024) +diff --git a/grub-core/disk/scsi.c b/grub-core/disk/scsi.c +index b6cb2f42109..92084d0f8ed 100644 +--- a/grub-core/disk/scsi.c ++++ b/grub-core/disk/scsi.c +@@ -201,7 +201,7 @@ grub_scsi_read_capacity16 (grub_scsi_t scsi) + rc.opcode = grub_scsi_cmd_read_capacity16; + rc.lun = (scsi->lun << GRUB_SCSI_LUN_SHIFT) | 0x10; + rc.logical_block_addr = 0; +- rc.alloc_len = grub_cpu_to_be32 (sizeof (rcd)); ++ rc.alloc_len = grub_cpu_to_be32_compile_time (sizeof (rcd)); + rc.PMI = 0; + rc.control = 0; + +diff --git a/grub-core/disk/usbms.c b/grub-core/disk/usbms.c +index 2b769bdd8e1..380ca4c4cbf 100644 +--- a/grub-core/disk/usbms.c ++++ b/grub-core/disk/usbms.c +@@ -307,7 +307,7 @@ grub_usbms_transfer_bo (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, + + /* Setup the request. */ + grub_memset (&cbw, 0, sizeof (cbw)); +- cbw.signature = grub_cpu_to_le32 (0x43425355); ++ cbw.signature = grub_cpu_to_le32_compile_time (0x43425355); + cbw.tag = tag; + cbw.transfer_length = grub_cpu_to_le32 (size); + cbw.flags = (!read_write) << GRUB_USBMS_DIRECTION_BIT; +@@ -414,7 +414,7 @@ CheckCSW: + + /* If phase error or not valid signature, do bulk-only reset device. */ + if ((status.status == 2) || +- (status.signature != grub_cpu_to_le32(0x53425355))) ++ (status.signature != grub_cpu_to_le32_compile_time(0x53425355))) + { /* Bulk-only reset device. */ + grub_dprintf ("usb", "Bulk-only reset device - bad status\n"); + grub_usbms_reset (dev); +diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c +index 1e593059a74..d1dc015455d 100644 +--- a/grub-core/fs/hfs.c ++++ b/grub-core/fs/hfs.c +@@ -369,7 +369,7 @@ grub_hfs_mount (grub_disk_t disk) + + /* Lookup the root directory node in the catalog tree using the + volume name. */ +- key.parent_dir = grub_cpu_to_be32 (1); ++ key.parent_dir = grub_cpu_to_be32_compile_time (1); + key.strlen = data->sblock.volname[0]; + grub_strcpy ((char *) key.str, (char *) (data->sblock.volname + 1)); + +diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c +index ac65054d363..de3d4fa3c64 100644 +--- a/grub-core/fs/reiserfs.c ++++ b/grub-core/fs/reiserfs.c +@@ -365,7 +365,7 @@ grub_reiserfs_set_key_offset (struct grub_reiserfs_key *key, + key->u.v1.offset = grub_cpu_to_le32 (value); + else + key->u.v2.offset_type \ +- = ((key->u.v2.offset_type & grub_cpu_to_le64 (15ULL << 60)) ++ = ((key->u.v2.offset_type & grub_cpu_to_le64_compile_time (15ULL << 60)) + | grub_cpu_to_le64 (value & (~0ULL >> 4))); + } + +@@ -412,7 +412,7 @@ grub_reiserfs_set_key_type (struct grub_reiserfs_key *key, + key->u.v1.type = grub_cpu_to_le32 (type); + else + key->u.v2.offset_type +- = ((key->u.v2.offset_type & grub_cpu_to_le64 (~0ULL >> 4)) ++ = ((key->u.v2.offset_type & grub_cpu_to_le64_compile_time (~0ULL >> 4)) + | grub_cpu_to_le64 ((grub_uint64_t) type << 60)); + + assert (grub_reiserfs_get_key_type (key) == grub_type); +@@ -997,8 +997,8 @@ grub_reiserfs_open (struct grub_file *file, const char *name) + data = grub_reiserfs_mount (file->device->disk); + if (! data) + goto fail; +- key.directory_id = grub_cpu_to_le32 (1); +- key.object_id = grub_cpu_to_le32 (2); ++ key.directory_id = grub_cpu_to_le32_compile_time (1); ++ key.object_id = grub_cpu_to_le32_compile_time (2); + key.u.v2.offset_type = 0; + grub_reiserfs_set_key_type (&key, GRUB_REISERFS_DIRECTORY, 2); + grub_reiserfs_set_key_offset (&key, 1); +@@ -1289,8 +1289,8 @@ grub_reiserfs_dir (grub_device_t device, const char *path, + data = grub_reiserfs_mount (device->disk); + if (! data) + goto fail; +- root_key.directory_id = grub_cpu_to_le32 (1); +- root_key.object_id = grub_cpu_to_le32 (2); ++ root_key.directory_id = grub_cpu_to_le32_compile_time (1); ++ root_key.object_id = grub_cpu_to_le32_compile_time (2); + root_key.u.v2.offset_type = 0; + grub_reiserfs_set_key_type (&root_key, GRUB_REISERFS_DIRECTORY, 2); + grub_reiserfs_set_key_offset (&root_key, 1); +diff --git a/grub-core/lib/fdt.c b/grub-core/lib/fdt.c +index 907a7bff61f..7e76dc06bbc 100644 +--- a/grub-core/lib/fdt.c ++++ b/grub-core/lib/fdt.c +@@ -164,10 +164,10 @@ static int add_subnode (void *fdt, int parentoffset, const char *name) + insert: + grub_memmove (token + entry_size / sizeof(*token), token, + (grub_addr_t) end - (grub_addr_t) token); +- *token = grub_cpu_to_be32(FDT_BEGIN_NODE); ++ *token = grub_cpu_to_be32_compile_time(FDT_BEGIN_NODE); + token[entry_size / sizeof(*token) - 2] = 0; /* padding bytes */ + grub_strcpy((char *) (token + 1), name); +- token[entry_size / sizeof(*token) - 1] = grub_cpu_to_be32(FDT_END_NODE); ++ token[entry_size / sizeof(*token) - 1] = grub_cpu_to_be32_compile_time(FDT_END_NODE); + grub_fdt_set_size_dt_struct (fdt, struct_size + entry_size); + return ((grub_addr_t) token - (grub_addr_t) fdt + - grub_fdt_get_off_dt_struct(fdt)); +@@ -377,7 +377,7 @@ int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name, + + prop_name_present = 1; + for (i = 0; i < prop_len / sizeof(grub_uint32_t); i++) +- *(prop + 3 + i) = grub_cpu_to_be32 (FDT_NOP); ++ *(prop + 3 + i) = grub_cpu_to_be32_compile_time (FDT_NOP); + if (len > ALIGN_UP(prop_len, sizeof(grub_uint32_t))) + { + /* Length of new property value is greater than the space allocated +@@ -385,7 +385,7 @@ int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name, + nameoff field of the current entry and replace the current entry + with NOP tokens. */ + nameoff = grub_be_to_cpu32 (*(prop + 2)); +- *prop = *(prop + 1) = *(prop + 2) = grub_cpu_to_be32 (FDT_NOP); ++ *prop = *(prop + 1) = *(prop + 2) = grub_cpu_to_be32_compile_time (FDT_NOP); + prop = NULL; + } + } +@@ -419,7 +419,7 @@ int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name, + struct_end(fdt) - (grub_addr_t) prop); + grub_fdt_set_size_dt_struct (fdt, grub_fdt_get_size_dt_struct (fdt) + + prop_entry_size(len)); +- *prop = grub_cpu_to_be32 (FDT_PROP); ++ *prop = grub_cpu_to_be32_compile_time (FDT_PROP); + *(prop + 2) = grub_cpu_to_be32 (nameoff); + } + *(prop + 1) = grub_cpu_to_be32 (len); +@@ -447,7 +447,7 @@ grub_fdt_create_empty_tree (void *fdt, unsigned int size) + et->empty_node.node_end = grub_cpu_to_be32_compile_time (FDT_END_NODE); + et->empty_node.node_start = grub_cpu_to_be32_compile_time (FDT_BEGIN_NODE); + ((struct grub_fdt_empty_tree *) fdt)->header.off_mem_rsvmap = +- grub_cpu_to_be32 (ALIGN_UP (sizeof (grub_fdt_header_t), 8)); ++ grub_cpu_to_be32_compile_time (ALIGN_UP (sizeof (grub_fdt_header_t), 8)); + + grub_fdt_set_off_dt_strings (fdt, sizeof (*et)); + grub_fdt_set_off_dt_struct (fdt, +diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c +index 764cde20318..e3906eb658f 100644 +--- a/grub-core/loader/i386/linux.c ++++ b/grub-core/loader/i386/linux.c +@@ -734,7 +734,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + + /* FIXME: 2.03 is not always good enough (Linux 2.4 can be 2.03 and + still not support 32-bit boot. */ +- if (lh.header != grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE) ++ if (lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE) + || grub_le_to_cpu16 (lh.version) < 0x0203) + { + grub_error (GRUB_ERR_BAD_OS, "version too old for 32-bit boot" +diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c +index 60bb31fbf0d..c2e5fa9abcc 100644 +--- a/grub-core/loader/i386/pc/linux.c ++++ b/grub-core/loader/i386/pc/linux.c +@@ -201,7 +201,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + + if (grub_le_to_cpu16 (lh.version) >= 0x0201) + { +- lh.heap_end_ptr = grub_cpu_to_le32_compile_time (GRUB_LINUX_HEAP_END_OFFSET); ++ lh.heap_end_ptr = grub_cpu_to_le16_compile_time (GRUB_LINUX_HEAP_END_OFFSET); + lh.loadflags |= GRUB_LINUX_FLAG_CAN_USE_HEAP; + } + +@@ -209,17 +209,17 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + lh.cmd_line_ptr = grub_linux_real_target + GRUB_LINUX_CL_OFFSET; + else + { +- lh.cl_magic = grub_cpu_to_le32_compile_time (GRUB_LINUX_CL_MAGIC); +- lh.cl_offset = grub_cpu_to_le32_compile_time (GRUB_LINUX_CL_OFFSET); +- lh.setup_move_size = grub_cpu_to_le32_compile_time (GRUB_LINUX_CL_OFFSET ++ lh.cl_magic = grub_cpu_to_le16_compile_time (GRUB_LINUX_CL_MAGIC); ++ lh.cl_offset = grub_cpu_to_le16_compile_time (GRUB_LINUX_CL_OFFSET); ++ lh.setup_move_size = grub_cpu_to_le16_compile_time (GRUB_LINUX_CL_OFFSET + + maximal_cmdline_size); + } + } + else + { + /* Your kernel is quite old... */ +- lh.cl_magic = grub_cpu_to_le32_compile_time (GRUB_LINUX_CL_MAGIC); +- lh.cl_offset = grub_cpu_to_le32_compile_time (GRUB_LINUX_CL_OFFSET); ++ lh.cl_magic = grub_cpu_to_le16_compile_time (GRUB_LINUX_CL_MAGIC); ++ lh.cl_offset = grub_cpu_to_le16_compile_time (GRUB_LINUX_CL_OFFSET); + + setup_sects = GRUB_LINUX_DEFAULT_SETUP_SECTS; + +diff --git a/grub-core/loader/i386/xen_file.c b/grub-core/loader/i386/xen_file.c +index ff23235f064..58362189098 100644 +--- a/grub-core/loader/i386/xen_file.c ++++ b/grub-core/loader/i386/xen_file.c +@@ -38,8 +38,8 @@ grub_xen_file (grub_file_t file) + if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) + goto fail; + +- if (lh.boot_flag != grub_cpu_to_le16 (0xaa55) +- || lh.header != grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE) ++ if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55) ++ || lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE) + || grub_le_to_cpu16 (lh.version) < 0x0208) + { + grub_error (GRUB_ERR_BAD_OS, "version too old for xen boot"); +diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c +index d62d0cc1e01..8cc390b0e28 100644 +--- a/grub-core/net/arp.c ++++ b/grub-core/net/arp.c +@@ -81,11 +81,11 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf, + return err; + + arp_header = (struct arphdr *) nb.data; +- arp_header->hrd = grub_cpu_to_be16 (GRUB_NET_ARPHRD_ETHERNET); ++ arp_header->hrd = grub_cpu_to_be16_compile_time (GRUB_NET_ARPHRD_ETHERNET); + arp_header->hln = 6; + arp_header->pro = grub_cpu_to_be16 (etherpro); + arp_header->pln = addrlen; +- arp_header->op = grub_cpu_to_be16 (ARP_REQUEST); ++ arp_header->op = grub_cpu_to_be16_compile_time (ARP_REQUEST); + aux = (grub_uint8_t *) arp_header + sizeof (*arp_header); + /* Sender hardware address. */ + grub_memcpy (aux, &inf->hwaddress.mac, 6); +diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c +index 46ce8135ac5..b4b8159cdad 100644 +--- a/grub-core/net/bootp.c ++++ b/grub-core/net/bootp.c +@@ -767,8 +767,8 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), + grub_netbuff_push (nb, sizeof (*udph)); + + udph = (struct udphdr *) nb->data; +- udph->src = grub_cpu_to_be16 (68); +- udph->dst = grub_cpu_to_be16 (67); ++ udph->src = grub_cpu_to_be16_compile_time (68); ++ udph->dst = grub_cpu_to_be16_compile_time (67); + udph->chksum = 0; + udph->len = grub_cpu_to_be16 (nb->tail - nb->data); + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; +diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c +index c6971f9fcd2..5a609544403 100644 +--- a/grub-core/net/ip.c ++++ b/grub-core/net/ip.c +@@ -611,7 +611,7 @@ grub_net_send_ip6_packet (struct grub_net_network_level_interface *inf, + grub_netbuff_push (nb, sizeof (*iph)); + iph = (struct ip6hdr *) nb->data; + +- iph->version_class_flow = grub_cpu_to_be32 ((6 << 28)); ++ iph->version_class_flow = grub_cpu_to_be32_compile_time ((6 << 28)); + iph->len = grub_cpu_to_be16 (nb->tail - nb->data - sizeof (*iph)); + iph->protocol = proto; + iph->ttl = 0xff; +diff --git a/grub-core/net/net.c b/grub-core/net/net.c +index 36fc0d8b2e8..fc6f714bf7f 100644 +--- a/grub-core/net/net.c ++++ b/grub-core/net/net.c +@@ -306,7 +306,7 @@ grub_net_ipv6_get_link_local (struct grub_net_card *card, + return NULL; + + addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; +- addr.ipv6[0] = grub_cpu_to_be64 (0xfe80ULL << 48); ++ addr.ipv6[0] = grub_cpu_to_be64_compile_time (0xfe80ULL << 48); + addr.ipv6[1] = grub_net_ipv6_get_id (hwaddr); + + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) +diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c +index 8632339de97..3931884c6dd 100644 +--- a/grub-core/net/tftp.c ++++ b/grub-core/net/tftp.c +@@ -149,7 +149,7 @@ ack (tftp_data_t data, grub_uint64_t block) + return err; + + tftph_ack = (struct tftphdr *) nb_ack.data; +- tftph_ack->opcode = grub_cpu_to_be16 (TFTP_ACK); ++ tftph_ack->opcode = grub_cpu_to_be16_compile_time (TFTP_ACK); + tftph_ack->u.ack.block = grub_cpu_to_be16 (block); + + err = grub_net_send_udp_packet (data->sock, &nb_ack); +@@ -352,7 +352,7 @@ tftp_open (struct grub_file *file, const char *filename) + rrq = (char *) tftph->u.rrq; + rrqlen = 0; + +- tftph->opcode = grub_cpu_to_be16 (TFTP_RRQ); ++ tftph->opcode = grub_cpu_to_be16_compile_time (TFTP_RRQ); + + /* Copy and normalize the filename to work-around issues on some tftp + servers when file names are being matched for remapping. */ +@@ -469,8 +469,8 @@ tftp_close (struct grub_file *file) + if (!err) + { + tftph = (struct tftphdr *) nb_err.data; +- tftph->opcode = grub_cpu_to_be16 (TFTP_ERROR); +- tftph->u.err.errcode = grub_cpu_to_be16 (TFTP_EUNDEF); ++ tftph->opcode = grub_cpu_to_be16_compile_time (TFTP_ERROR); ++ tftph->u.err.errcode = grub_cpu_to_be16_compile_time (TFTP_EUNDEF); + grub_memcpy (tftph->u.err.errmsg, "closed", sizeof ("closed")); + + err = grub_net_send_udp_packet (data->sock, &nb_err); +diff --git a/grub-core/partmap/acorn.c b/grub-core/partmap/acorn.c +index 7bb93d9bec9..c022c61ddfc 100644 +--- a/grub-core/partmap/acorn.c ++++ b/grub-core/partmap/acorn.c +@@ -25,8 +25,8 @@ + + GRUB_MOD_LICENSE ("GPLv3+"); + +-#define LINUX_NATIVE_MAGIC grub_cpu_to_le32 (0xdeafa1de) +-#define LINUX_SWAP_MAGIC grub_cpu_to_le32 (0xdeafab1e) ++#define LINUX_NATIVE_MAGIC grub_cpu_to_le32_compile_time (0xdeafa1de) ++#define LINUX_SWAP_MAGIC grub_cpu_to_le32_compile_time (0xdeafab1e) + #define LINUX_MAP_ENTRIES (512 / 12) + + #define NONADFS_PARTITION_TYPE_LINUX 9 +diff --git a/grub-core/partmap/bsdlabel.c b/grub-core/partmap/bsdlabel.c +index cf0f967c1fa..1d785906b6a 100644 +--- a/grub-core/partmap/bsdlabel.c ++++ b/grub-core/partmap/bsdlabel.c +@@ -53,7 +53,7 @@ iterate_real (grub_disk_t disk, grub_disk_addr_t sector, int freebsd, + return grub_errno; + + /* Check if it is valid. */ +- if (label.magic != grub_cpu_to_le32 (GRUB_PC_PARTITION_BSD_LABEL_MAGIC)) ++ if (label.magic != grub_cpu_to_le32_compile_time (GRUB_PC_PARTITION_BSD_LABEL_MAGIC)) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature"); + + /* A kludge to determine a base of be.offset. */ +diff --git a/grub-core/partmap/gpt.c b/grub-core/partmap/gpt.c +index 38df7b3c9b8..83bcba77914 100644 +--- a/grub-core/partmap/gpt.c ++++ b/grub-core/partmap/gpt.c +@@ -65,7 +65,7 @@ grub_gpt_partition_map_iterate (grub_disk_t disk, + return grub_errno; + + /* Check if it is valid. */ +- if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE)) ++ if (mbr.signature != grub_cpu_to_le16_compile_time (GRUB_PC_PARTITION_SIGNATURE)) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature"); + + /* Make sure the MBR is a protective MBR and not a normal MBR. */ +diff --git a/grub-core/partmap/msdos.c b/grub-core/partmap/msdos.c +index 1d81a53573b..46c406bff1f 100644 +--- a/grub-core/partmap/msdos.c ++++ b/grub-core/partmap/msdos.c +@@ -162,7 +162,7 @@ grub_partition_msdos_iterate (grub_disk_t disk, + lastaddr = p.offset; + + /* Check if it is valid. */ +- if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE)) ++ if (mbr.signature != grub_cpu_to_le16_compile_time (GRUB_PC_PARTITION_SIGNATURE)) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature"); + + for (i = 0; i < 4; i++) +@@ -280,7 +280,7 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, + lastaddr = offset; + + /* Check if it is valid. */ +- if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE)) ++ if (mbr.signature != grub_cpu_to_le16_compile_time (GRUB_PC_PARTITION_SIGNATURE)) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature"); + + for (i = 0; i < 4; i++) +diff --git a/grub-core/tests/video_checksum.c b/grub-core/tests/video_checksum.c +index 491bc55731c..74d5b65e5c7 100644 +--- a/grub-core/tests/video_checksum.c ++++ b/grub-core/tests/video_checksum.c +@@ -288,16 +288,16 @@ grub_video_capture_write_bmp (const char *fname, + if (mode_info->mode_type & GRUB_VIDEO_MODE_TYPE_RGB) + { + head.filesize = grub_cpu_to_le32 (sizeof (head) + mode_info->width * mode_info->height * 3); +- head.bmp_off = grub_cpu_to_le32 (sizeof (head)); ++ head.bmp_off = grub_cpu_to_le32_compile_time (sizeof (head)); + head.bpp = grub_cpu_to_le16_compile_time (24); + } + else + { + head.filesize = grub_cpu_to_le32 (sizeof (head) + 3 * 256 + mode_info->width * mode_info->height); +- head.bmp_off = grub_cpu_to_le32 (sizeof (head) + 3 * 256); ++ head.bmp_off = grub_cpu_to_le32_compile_time (sizeof (head) + 3 * 256); + head.bpp = grub_cpu_to_le16_compile_time (8); + } +- head.head_size = grub_cpu_to_le32 (sizeof (head) - 14); ++ head.head_size = grub_cpu_to_le32_compile_time (sizeof (head) - 14); + head.width = grub_cpu_to_le16 (mode_info->width); + head.height = grub_cpu_to_le16 (mode_info->height); + head.planes = grub_cpu_to_le16_compile_time (1); +diff --git a/util/grub-mkfont.c b/util/grub-mkfont.c +index e6485b40f28..a0cab3a93f8 100644 +--- a/util/grub-mkfont.c ++++ b/util/grub-mkfont.c +@@ -704,7 +704,7 @@ write_be16_section (const char *name, grub_uint16_t data, int* offset, + { + grub_uint32_t leng; + +- leng = grub_cpu_to_be32 (2); ++ leng = grub_cpu_to_be32_compile_time (2); + data = grub_cpu_to_be16 (data); + grub_util_write_image (name, 4, file, filename); + grub_util_write_image ((char *) &leng, 4, file, filename); +@@ -801,7 +801,7 @@ write_font_pf2 (struct grub_font_info *font_info, char *output_file) + + offset = 0; + +- leng = grub_cpu_to_be32 (4); ++ leng = grub_cpu_to_be32_compile_time (4); + grub_util_write_image (FONT_FORMAT_SECTION_NAMES_FILE, + sizeof(FONT_FORMAT_SECTION_NAMES_FILE) - 1, file, + output_file); +diff --git a/util/grub-mklayout.c b/util/grub-mklayout.c +index 692f881900b..1a4f1b4c855 100644 +--- a/util/grub-mklayout.c ++++ b/util/grub-mklayout.c +@@ -329,7 +329,7 @@ write_file (FILE *out, const char *fname, struct grub_keyboard_layout *layout) + grub_uint32_t version; + unsigned i; + +- version = grub_cpu_to_le32 (GRUB_KEYBOARD_LAYOUTS_VERSION); ++ version = grub_cpu_to_le32_compile_time (GRUB_KEYBOARD_LAYOUTS_VERSION); + + for (i = 0; i < ARRAY_SIZE (layout->keyboard_map); i++) + layout->keyboard_map[i] = grub_cpu_to_le32(layout->keyboard_map[i]); +diff --git a/util/mkimage.c b/util/mkimage.c +index 26d9816e07e..e6b799fd73c 100644 +--- a/util/mkimage.c ++++ b/util/mkimage.c +@@ -1528,9 +1528,10 @@ grub_install_generate_image (const char *dir, const char *prefix, + text_section->virtual_address = grub_cpu_to_le32 (header_size); + text_section->raw_data_size = grub_cpu_to_le32 (exec_size); + text_section->raw_data_offset = grub_cpu_to_le32 (header_size); +- text_section->characteristics = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_CODE +- | GRUB_PE32_SCN_MEM_EXECUTE +- | GRUB_PE32_SCN_MEM_READ); ++ text_section->characteristics = grub_cpu_to_le32_compile_time ( ++ GRUB_PE32_SCN_CNT_CODE ++ | GRUB_PE32_SCN_MEM_EXECUTE ++ | GRUB_PE32_SCN_MEM_READ); + + data_section = text_section + 1; + strcpy (data_section->name, ".data"); +@@ -1539,7 +1540,7 @@ grub_install_generate_image (const char *dir, const char *prefix, + data_section->raw_data_size = grub_cpu_to_le32 (kernel_size - exec_size); + data_section->raw_data_offset = grub_cpu_to_le32 (header_size + exec_size); + data_section->characteristics +- = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA ++ = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA + | GRUB_PE32_SCN_MEM_READ + | GRUB_PE32_SCN_MEM_WRITE); + +@@ -1551,7 +1552,7 @@ grub_install_generate_image (const char *dir, const char *prefix, + bss_section->raw_data_size = 0; + bss_section->raw_data_offset = 0; + bss_section->characteristics +- = grub_cpu_to_le32 (GRUB_PE32_SCN_MEM_READ ++ = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_MEM_READ + | GRUB_PE32_SCN_MEM_WRITE + | GRUB_PE32_SCN_ALIGN_64BYTES + | GRUB_PE32_SCN_CNT_INITIALIZED_DATA +@@ -1565,7 +1566,7 @@ grub_install_generate_image (const char *dir, const char *prefix, + mods_section->raw_data_size = grub_cpu_to_le32 (reloc_addr - kernel_size - header_size); + mods_section->raw_data_offset = grub_cpu_to_le32 (header_size + kernel_size); + mods_section->characteristics +- = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA ++ = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA + | GRUB_PE32_SCN_MEM_READ + | GRUB_PE32_SCN_MEM_WRITE); + +@@ -1576,7 +1577,7 @@ grub_install_generate_image (const char *dir, const char *prefix, + reloc_section->raw_data_size = grub_cpu_to_le32 (reloc_size); + reloc_section->raw_data_offset = grub_cpu_to_le32 (reloc_addr); + reloc_section->characteristics +- = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA ++ = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA + | GRUB_PE32_SCN_MEM_DISCARDABLE + | GRUB_PE32_SCN_MEM_READ); + free (core_img); diff --git a/SOURCES/0243-arp-icmp-Fix-handling-in-case-of-oversized-or-invali.patch b/SOURCES/0243-arp-icmp-Fix-handling-in-case-of-oversized-or-invali.patch new file mode 100644 index 0000000..7d3faa6 --- /dev/null +++ b/SOURCES/0243-arp-icmp-Fix-handling-in-case-of-oversized-or-invali.patch @@ -0,0 +1,309 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Fri, 20 Mar 2015 21:14:23 +0100 +Subject: [PATCH] arp, icmp: Fix handling in case of oversized or invalid + packets. + +This restrict ARP handling to MAC and IP addresses but in practice we need +only this case anyway and other cases are very rar if exist at all. It makes +code much simpler and less error-prone. +--- + grub-core/net/arp.c | 139 ++++++++++++++++++++++----------------------- + grub-core/net/icmp.c | 14 +---- + grub-core/net/netbuff.c | 20 +++++++ + include/grub/net/netbuff.h | 1 + + 4 files changed, 90 insertions(+), 84 deletions(-) + +diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c +index 8cc390b0e28..6cc580d6f85 100644 +--- a/grub-core/net/arp.c ++++ b/grub-core/net/arp.c +@@ -37,12 +37,16 @@ enum + GRUB_NET_ARPHRD_ETHERNET = 1 + }; + +-struct arphdr { ++struct arppkt { + grub_uint16_t hrd; + grub_uint16_t pro; + grub_uint8_t hln; + grub_uint8_t pln; + grub_uint16_t op; ++ grub_uint8_t sender_mac[6]; ++ grub_uint32_t sender_ip; ++ grub_uint8_t recv_mac[6]; ++ grub_uint32_t recv_ip; + } GRUB_PACKED; + + static int have_pending; +@@ -53,21 +57,14 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *proto_addr) + { + struct grub_net_buff nb; +- struct arphdr *arp_header; +- grub_net_link_level_address_t target_hw_addr; +- grub_uint8_t *aux, arp_data[128]; ++ struct arppkt *arp_packet; ++ grub_net_link_level_address_t target_mac_addr; + grub_err_t err; + int i; +- grub_size_t addrlen; +- grub_uint16_t etherpro; + grub_uint8_t *nbd; ++ grub_uint8_t arp_data[128]; + +- if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) +- { +- addrlen = 4; +- etherpro = GRUB_NET_ETHERTYPE_IP; +- } +- else ++ if (proto_addr->type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) + return grub_error (GRUB_ERR_BUG, "unsupported address family"); + + /* Build a request packet. */ +@@ -76,34 +73,28 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf, + grub_netbuff_clear (&nb); + grub_netbuff_reserve (&nb, 128); + +- err = grub_netbuff_push (&nb, sizeof (*arp_header) + 2 * (6 + addrlen)); ++ err = grub_netbuff_push (&nb, sizeof (*arp_packet)); + if (err) + return err; + +- arp_header = (struct arphdr *) nb.data; +- arp_header->hrd = grub_cpu_to_be16_compile_time (GRUB_NET_ARPHRD_ETHERNET); +- arp_header->hln = 6; +- arp_header->pro = grub_cpu_to_be16 (etherpro); +- arp_header->pln = addrlen; +- arp_header->op = grub_cpu_to_be16_compile_time (ARP_REQUEST); +- aux = (grub_uint8_t *) arp_header + sizeof (*arp_header); ++ arp_packet = (struct arppkt *) nb.data; ++ arp_packet->hrd = grub_cpu_to_be16_compile_time (GRUB_NET_ARPHRD_ETHERNET); ++ arp_packet->hln = 6; ++ arp_packet->pro = grub_cpu_to_be16 (GRUB_NET_ETHERTYPE_IP); ++ arp_packet->pln = 4; ++ arp_packet->op = grub_cpu_to_be16_compile_time (ARP_REQUEST); + /* Sender hardware address. */ + grub_memcpy (aux, &inf->hwaddress.mac, 6); + +- aux += 6; +- /* Sender protocol address */ +- grub_memcpy (aux, &inf->address.ipv4, 4); +- aux += addrlen; +- /* Target hardware address */ +- for (i = 0; i < 6; i++) +- aux[i] = 0x00; +- aux += 6; ++ grub_memcpy (arp_packet->sender_mac, &inf->hwaddress.mac, 6); ++ arp_packet->sender_ip = inf->address.ipv4; ++ grub_memset (arp_packet->recv_mac, 0, 6); ++ arp_packet->recv_ip = proto_addr->ipv4; + /* Target protocol address */ +- grub_memcpy (aux, &proto_addr->ipv4, 4); +- grub_memset (&target_hw_addr.mac, 0xff, 6); ++ grub_memset (&target_mac_addr.mac, 0xff, 6); + + nbd = nb.data; +- send_ethernet_packet (inf, &nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP); ++ send_ethernet_packet (inf, &nb, target_mac_addr, GRUB_NET_ETHERTYPE_ARP); + for (i = 0; i < GRUB_NET_TRIES; i++) + { + if (grub_net_link_layer_resolve_check (inf, proto_addr)) +@@ -115,7 +106,7 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf, + if (grub_net_link_layer_resolve_check (inf, proto_addr)) + return GRUB_ERR_NONE; + nb.data = nbd; +- send_ethernet_packet (inf, &nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP); ++ send_ethernet_packet (inf, &nb, target_mac_addr, GRUB_NET_ETHERTYPE_ARP); + } + + return GRUB_ERR_NONE; +@@ -125,63 +116,67 @@ grub_err_t + grub_net_arp_receive (struct grub_net_buff *nb, + struct grub_net_card *card) + { +- struct arphdr *arp_header = (struct arphdr *) nb->data; +- grub_uint8_t *sender_hardware_address; +- grub_uint8_t *target_hardware_address; ++ struct arppkt *arp_packet = (struct arppkt *) nb->data; + grub_net_network_level_address_t sender_addr, target_addr; +- grub_net_link_level_address_t sender_hw_addr; ++ grub_net_link_level_address_t sender_mac_addr; + struct grub_net_network_level_interface *inf; +- grub_uint8_t *sender_protocol_address, *target_protocol_address; + +- sender_hardware_address = +- (grub_uint8_t *) arp_header + sizeof (*arp_header); +- sender_protocol_address = sender_hardware_address + arp_header->hln; +- target_hardware_address = sender_protocol_address + arp_header->pln; +- target_protocol_address = target_hardware_address + arp_header->hln; +- if (grub_be_to_cpu16 (arp_header->pro) == GRUB_NET_ETHERTYPE_IP +- && arp_header->pln == 4) +- { +- sender_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; +- target_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; +- grub_memcpy (&sender_addr.ipv4, sender_protocol_address, 4); +- grub_memcpy (&target_addr.ipv4, target_protocol_address, 4); +- if (grub_memcmp (sender_protocol_address, &pending_req, 4) == 0) +- have_pending = 1; +- } +- else ++ if (arp_packet->pro != grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP) ++ || arp_packet->pln != 4 || arp_packet->hln != 6 ++ || nb->tail - nb->data < (int) sizeof (*arp_packet)) + return GRUB_ERR_NONE; + +- sender_hw_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; +- grub_memcpy (sender_hw_addr.mac, sender_hardware_address, +- sizeof (sender_hw_addr.mac)); +- grub_net_link_layer_add_address (card, &sender_addr, &sender_hw_addr, 1); ++ sender_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; ++ target_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; ++ sender_addr.ipv4 = arp_packet->sender_ip; ++ target_addr.ipv4 = arp_packet->recv_ip; ++ if (arp_packet->sender_ip == pending_req) ++ have_pending = 1; ++ ++ sender_mac_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; ++ grub_memcpy (sender_mac_addr.mac, arp_packet->sender_mac, ++ sizeof (sender_mac_addr.mac)); ++ grub_net_link_layer_add_address (card, &sender_addr, &sender_mac_addr, 1); + + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + { + /* Am I the protocol address target? */ + if (grub_net_addr_cmp (&inf->address, &target_addr) == 0 +- && grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST) ++ && arp_packet->op == grub_cpu_to_be16_compile_time (ARP_REQUEST)) + { + grub_net_link_level_address_t target; +- /* We've already checked that pln is either 4 or 16. */ +- char tmp[16]; +- grub_size_t pln = arp_header->pln; ++ struct grub_net_buff nb_reply; ++ struct arppkt *arp_reply; ++ grub_uint8_t arp_data[128]; ++ grub_err_t err; + +- if (pln > 16) +- pln = 16; ++ nb_reply.head = arp_data; ++ nb_reply.end = arp_data + sizeof (arp_data); ++ grub_netbuff_clear (&nb_reply); ++ grub_netbuff_reserve (&nb_reply, 128); ++ ++ err = grub_netbuff_push (&nb_reply, sizeof (*arp_packet)); ++ if (err) ++ return err; ++ ++ arp_reply = (struct arppkt *) nb_reply.data; ++ ++ arp_reply->hrd = grub_cpu_to_be16_compile_time (GRUB_NET_ARPHRD_ETHERNET); ++ arp_reply->pro = grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP); ++ arp_reply->pln = 4; ++ arp_reply->hln = 6; ++ arp_reply->op = grub_cpu_to_be16_compile_time (ARP_REPLY); ++ arp_reply->sender_ip = arp_packet->recv_ip; ++ arp_reply->recv_ip = arp_packet->sender_ip; ++ arp_reply->hln = 6; + + target.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; +- grub_memcpy (target.mac, sender_hardware_address, 6); +- grub_memcpy (target_hardware_address, target.mac, 6); +- grub_memcpy (sender_hardware_address, inf->hwaddress.mac, 6); +- +- grub_memcpy (tmp, sender_protocol_address, pln); +- grub_memcpy (sender_protocol_address, target_protocol_address, pln); +- grub_memcpy (target_protocol_address, tmp, pln); ++ grub_memcpy (target.mac, arp_packet->sender_mac, 6); ++ grub_memcpy (arp_reply->sender_mac, inf->hwaddress.mac, 6); ++ grub_memcpy (arp_reply->recv_mac, arp_packet->sender_mac, 6); + + /* Change operation to REPLY and send packet */ +- arp_header->op = grub_be_to_cpu16 (ARP_REPLY); +- send_ethernet_packet (inf, nb, target, GRUB_NET_ETHERTYPE_ARP); ++ send_ethernet_packet (inf, &nb_reply, target, GRUB_NET_ETHERTYPE_ARP); + } + } + return GRUB_ERR_NONE; +diff --git a/grub-core/net/icmp.c b/grub-core/net/icmp.c +index 28d825ba04c..b1eef114e03 100644 +--- a/grub-core/net/icmp.c ++++ b/grub-core/net/icmp.c +@@ -85,22 +85,13 @@ grub_net_recv_icmp_packet (struct grub_net_buff *nb, + struct icmp_header *icmphr; + if (icmph->code) + break; +- nb_reply = grub_netbuff_alloc (nb->tail - nb->data + 512); ++ nb_reply = grub_netbuff_make_pkt (nb->tail - nb->data + sizeof (*icmphr)); + if (!nb_reply) + { + grub_netbuff_free (nb); + return grub_errno; + } +- err = grub_netbuff_reserve (nb_reply, nb->tail - nb->data + 512); +- if (err) +- goto ping_fail; +- err = grub_netbuff_push (nb_reply, nb->tail - nb->data); +- if (err) +- goto ping_fail; +- grub_memcpy (nb_reply->data, nb->data, nb->tail - nb->data); +- err = grub_netbuff_push (nb_reply, sizeof (*icmphr)); +- if (err) +- goto ping_fail; ++ grub_memcpy (nb_reply->data + sizeof (*icmphr), nb->data, nb->tail - nb->data); + icmphr = (struct icmp_header *) nb_reply->data; + icmphr->type = ICMP_ECHO_REPLY; + icmphr->code = 0; +@@ -110,7 +101,6 @@ grub_net_recv_icmp_packet (struct grub_net_buff *nb, + err = grub_net_send_ip_packet (inf, src, ll_src, + nb_reply, GRUB_NET_IP_ICMP); + +- ping_fail: + grub_netbuff_free (nb); + grub_netbuff_free (nb_reply); + return err; +diff --git a/grub-core/net/netbuff.c b/grub-core/net/netbuff.c +index e97ecd23e9c..dbeeefe4783 100644 +--- a/grub-core/net/netbuff.c ++++ b/grub-core/net/netbuff.c +@@ -97,6 +97,26 @@ grub_netbuff_alloc (grub_size_t len) + return nb; + } + ++struct grub_net_buff * ++grub_netbuff_make_pkt (grub_size_t len) ++{ ++ struct grub_net_buff *nb; ++ grub_err_t err; ++ nb = grub_netbuff_alloc (len + 512); ++ if (!nb) ++ return NULL; ++ err = grub_netbuff_reserve (nb, len + 512); ++ if (err) ++ goto fail; ++ err = grub_netbuff_push (nb, len); ++ if (err) ++ goto fail; ++ return nb; ++ fail: ++ grub_netbuff_free (nb); ++ return NULL; ++} ++ + void + grub_netbuff_free (struct grub_net_buff *nb) + { +diff --git a/include/grub/net/netbuff.h b/include/grub/net/netbuff.h +index 9ac168c897c..1177c122051 100644 +--- a/include/grub/net/netbuff.h ++++ b/include/grub/net/netbuff.h +@@ -25,6 +25,7 @@ grub_err_t grub_netbuff_pull (struct grub_net_buff *net_buff, grub_size_t len); + grub_err_t grub_netbuff_reserve (struct grub_net_buff *net_buff, grub_size_t len); + grub_err_t grub_netbuff_clear (struct grub_net_buff *net_buff); + struct grub_net_buff * grub_netbuff_alloc (grub_size_t len); ++struct grub_net_buff * grub_netbuff_make_pkt (grub_size_t len); + void grub_netbuff_free (struct grub_net_buff *net_buff); + + #endif diff --git a/SOURCES/0244-net-trivial-grub_cpu_to_XX_compile_time-cleanup.patch b/SOURCES/0244-net-trivial-grub_cpu_to_XX_compile_time-cleanup.patch new file mode 100644 index 0000000..e1249a9 --- /dev/null +++ b/SOURCES/0244-net-trivial-grub_cpu_to_XX_compile_time-cleanup.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Fri, 27 Mar 2015 18:58:57 +0300 +Subject: [PATCH] net: trivial grub_cpu_to_XX_compile_time cleanup + +--- + grub-core/net/arp.c | 2 +- + grub-core/net/icmp6.c | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c +index 6cc580d6f85..996473e1091 100644 +--- a/grub-core/net/arp.c ++++ b/grub-core/net/arp.c +@@ -80,7 +80,7 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf, + arp_packet = (struct arppkt *) nb.data; + arp_packet->hrd = grub_cpu_to_be16_compile_time (GRUB_NET_ARPHRD_ETHERNET); + arp_packet->hln = 6; +- arp_packet->pro = grub_cpu_to_be16 (GRUB_NET_ETHERTYPE_IP); ++ arp_packet->pro = grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP); + arp_packet->pln = 4; + arp_packet->op = grub_cpu_to_be16_compile_time (ARP_REQUEST); + /* Sender hardware address. */ +diff --git a/grub-core/net/icmp6.c b/grub-core/net/icmp6.c +index 78223946031..7953e68ecfa 100644 +--- a/grub-core/net/icmp6.c ++++ b/grub-core/net/icmp6.c +@@ -552,8 +552,8 @@ grub_net_icmp6_send_router_solicit (struct grub_net_network_level_interface *inf + struct icmp_header *icmphr; + + multicast.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; +- multicast.ipv6[0] = grub_cpu_to_be64 (0xff02ULL << 48); +- multicast.ipv6[1] = grub_cpu_to_be64 (0x02ULL); ++ multicast.ipv6[0] = grub_cpu_to_be64_compile_time (0xff02ULL << 48); ++ multicast.ipv6[1] = grub_cpu_to_be64_compile_time (0x02ULL); + + err = grub_net_link_layer_resolve (inf, &multicast, &ll_multicast); + if (err) diff --git a/SOURCES/0245-bootp-ignore-gateway_ip-relay-field.patch b/SOURCES/0245-bootp-ignore-gateway_ip-relay-field.patch new file mode 100644 index 0000000..53cfb25 --- /dev/null +++ b/SOURCES/0245-bootp-ignore-gateway_ip-relay-field.patch @@ -0,0 +1,72 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Sun, 17 May 2015 22:38:30 +0300 +Subject: [PATCH] bootp: ignore gateway_ip (relay) field. + +From RFC1542: + + The 'giaddr' field is rather poorly named. It exists to facilitate + the transfer of BOOTREQUEST messages from a client, through BOOTP + relay agents, to servers on different networks than the client. + Similarly, it facilitates the delivery of BOOTREPLY messages from the + servers, through BOOTP relay agents, back to the client. In no case + does it represent a general IP router to be used by the client. A + BOOTP client MUST set the 'giaddr' field to zero (0.0.0.0) in all + BOOTREQUEST messages it generates. + + A BOOTP client MUST NOT interpret the 'giaddr' field of a BOOTREPLY + message to be the IP address of an IP router. A BOOTP client SHOULD + completely ignore the contents of the 'giaddr' field in BOOTREPLY + messages. + +Leave code ifdef'd out for the time being in case we see regression. + +Suggested by: Rink Springer +Closes: 43396 +--- + grub-core/net/bootp.c | 7 +++++++ + docs/grub.texi | 6 ++++-- + 2 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c +index b4b8159cdad..62d602d9645 100644 +--- a/grub-core/net/bootp.c ++++ b/grub-core/net/bootp.c +@@ -237,6 +237,12 @@ grub_net_configure_by_dhcp_ack (const char *name, + hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + + inter = grub_net_add_addr (name, card, &addr, &hwaddr, flags); ++#if 0 ++ /* This is likely based on misunderstanding. gateway_ip refers to ++ address of BOOTP relay and should not be used after BOOTP transaction ++ is complete. ++ See RFC1542, 3.4 Interpretation of the 'giaddr' field ++ */ + if (bp->gateway_ip) + { + grub_net_network_level_netaddress_t target; +@@ -258,6 +264,7 @@ grub_net_configure_by_dhcp_ack (const char *name, + target.ipv4.masksize = 32; + grub_net_add_route (name, target, inter); + } ++#endif + + if (size > OFFSET_OF (boot_file, bp)) + grub_env_set_net_property (name, "boot_file", bp->boot_file, +diff --git a/docs/grub.texi b/docs/grub.texi +index ef09c832482..98138e04d5b 100644 +--- a/docs/grub.texi ++++ b/docs/grub.texi +@@ -5211,8 +5211,10 @@ by @var{shortname} which can be used to remove it (@pxref{net_del_route}). + Perform configuration of @var{card} using DHCP protocol. If no card name + is specified, try to configure all existing cards. If configuration was + successful, interface with name @var{card}@samp{:dhcp} and configured +-address is added to @var{card}. If server provided gateway information in +-DHCP ACK packet, it is added as route entry with the name @var{card}@samp{:dhcp:gw}. Additionally the following DHCP options are recognized and processed: ++address is added to @var{card}. ++@comment If server provided gateway information in ++@comment DHCP ACK packet, it is added as route entry with the name @var{card}@samp{:dhcp:gw}. ++Additionally the following DHCP options are recognized and processed: + + @table @samp + @item 1 (Subnet Mask) diff --git a/SOURCES/0246-bootp-check-that-interface-is-not-NULL-in-configure_.patch b/SOURCES/0246-bootp-check-that-interface-is-not-NULL-in-configure_.patch new file mode 100644 index 0000000..2132f27 --- /dev/null +++ b/SOURCES/0246-bootp-check-that-interface-is-not-NULL-in-configure_.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Sun, 20 Mar 2016 10:32:33 +0300 +Subject: [PATCH] bootp: check that interface is not NULL in + configure_by_dhcp_ack + +grub_net_add_addr may fail with OOM and we use returned interface +later without any checks. +--- + grub-core/net/bootp.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c +index 62d602d9645..7df7f55110e 100644 +--- a/grub-core/net/bootp.c ++++ b/grub-core/net/bootp.c +@@ -237,6 +237,9 @@ grub_net_configure_by_dhcp_ack (const char *name, + hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + + inter = grub_net_add_addr (name, card, &addr, &hwaddr, flags); ++ if (!inter) ++ return 0; ++ + #if 0 + /* This is likely based on misunderstanding. gateway_ip refers to + address of BOOTP relay and should not be used after BOOTP transaction diff --git a/SOURCES/0247-Use-xid-to-match-DHCP-replies.patch b/SOURCES/0247-Use-xid-to-match-DHCP-replies.patch new file mode 100644 index 0000000..95b3ffb --- /dev/null +++ b/SOURCES/0247-Use-xid-to-match-DHCP-replies.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrzej Kacprowski +Date: Fri, 21 Apr 2017 09:20:38 +0200 +Subject: [PATCH] Use xid to match DHCP replies + +Transaction identifier (xid) from DHCP request +packet is stored in network level interface and used +to match request with the responses it generates. + +Resolves: rhbz#1370642 + +Signed-off-by: Andrzej Kacprowski +--- + grub-core/net/bootp.c | 3 ++- + grub-core/net/ip.c | 1 + + include/grub/net.h | 3 ++- + 3 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c +index 7df7f55110e..dfdf7e08d90 100644 +--- a/grub-core/net/bootp.c ++++ b/grub-core/net/bootp.c +@@ -769,7 +769,8 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), + grub_errno = GRUB_ERR_NONE; + t = 0; + } +- pack->ident = grub_cpu_to_be32 (t); ++ pack->xid = grub_cpu_to_be32 (t); ++ ifaces[j].dhcp_xid = pack->xid; + pack->seconds = grub_cpu_to_be16 (t); + + grub_memcpy (&pack->mac_addr, &ifaces[j].hwaddress.mac, 6); +diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c +index 5a609544403..9e7930caa03 100644 +--- a/grub-core/net/ip.c ++++ b/grub-core/net/ip.c +@@ -271,6 +271,7 @@ handle_dgram (struct grub_net_buff *nb, + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + if (inf->card == card + && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV ++ && inf->dhcp_xid == bootp->xid + && inf->hwaddress.type == GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET + && grub_memcmp (inf->hwaddress.mac, &bootp->mac_addr, + sizeof (inf->hwaddress.mac)) == 0) +diff --git a/include/grub/net.h b/include/grub/net.h +index bd930f4dd8c..b1bc23048f1 100644 +--- a/include/grub/net.h ++++ b/include/grub/net.h +@@ -279,6 +279,7 @@ struct grub_net_network_level_interface + grub_net_interface_flags_t flags; + struct grub_net_bootp_packet *dhcp_ack; + grub_size_t dhcp_acklen; ++ grub_uint32_t dhcp_xid; + void *data; + }; + +@@ -405,7 +406,7 @@ struct grub_net_bootp_packet + grub_uint8_t hw_type; /* hardware type. */ + grub_uint8_t hw_len; /* hardware addr len. */ + grub_uint8_t gate_hops; /* zero it. */ +- grub_uint32_t ident; /* random number chosen by client. */ ++ grub_uint32_t xid; /* transaction id chosen by client. */ + grub_uint16_t seconds; /* seconds since did initial bootstrap. */ + grub_uint16_t flags; + grub_uint32_t client_ip; diff --git a/SOURCES/0248-Add-support-for-non-Ethernet-network-cards.patch b/SOURCES/0248-Add-support-for-non-Ethernet-network-cards.patch new file mode 100644 index 0000000..48bf748 --- /dev/null +++ b/SOURCES/0248-Add-support-for-non-Ethernet-network-cards.patch @@ -0,0 +1,758 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrzej Kacprowski +Date: Fri, 21 Apr 2017 10:06:20 +0200 +Subject: [PATCH] Add support for non-Ethernet network cards + +This patch replaces fixed 6-byte link layer address with +up to 32-byte variable sized address. +This allows supporting Infiniband and Omni-Path fabric +which use 20-byte address, but other network card types +can also take advantage of this change. +The network card driver is responsible for replacing L2 +header provided by grub2 if needed. +This approach is compatible with UEFI network stack which +also allows up to 32-byte variable size link address. + +The BOOTP/DHCP packet format is limited to 16 byte client +hardware address, if link address is more that 16-bytes +then chaddr field in BOOTP it will be set to 0 as per rfc4390. + +Resolves: rhbz#1370642 + +Signed-off-by: Andrzej Kacprowski + +Conflicts: + grub-core/net/ip.c +--- + grub-core/net/arp.c | 157 +++++++++++++++++++++------------ + grub-core/net/bootp.c | 14 ++- + grub-core/net/drivers/efi/efinet.c | 8 +- + grub-core/net/drivers/emu/emunet.c | 1 + + grub-core/net/drivers/i386/pc/pxe.c | 13 +-- + grub-core/net/drivers/ieee1275/ofnet.c | 2 + + grub-core/net/drivers/uboot/ubootnet.c | 1 + + grub-core/net/ethernet.c | 83 +++++++++-------- + grub-core/net/icmp6.c | 15 ++-- + grub-core/net/ip.c | 4 +- + grub-core/net/net.c | 48 +++++----- + include/grub/net.h | 19 ++-- + 12 files changed, 213 insertions(+), 152 deletions(-) + +diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c +index 996473e1091..badd2d3e684 100644 +--- a/grub-core/net/arp.c ++++ b/grub-core/net/arp.c +@@ -31,22 +31,12 @@ enum + ARP_REPLY = 2 + }; + +-enum +- { +- /* IANA ARP constant to define hardware type as ethernet. */ +- GRUB_NET_ARPHRD_ETHERNET = 1 +- }; +- +-struct arppkt { ++struct arphdr { + grub_uint16_t hrd; + grub_uint16_t pro; + grub_uint8_t hln; + grub_uint8_t pln; + grub_uint16_t op; +- grub_uint8_t sender_mac[6]; +- grub_uint32_t sender_ip; +- grub_uint8_t recv_mac[6]; +- grub_uint32_t recv_ip; + } GRUB_PACKED; + + static int have_pending; +@@ -57,12 +47,16 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *proto_addr) + { + struct grub_net_buff nb; +- struct arppkt *arp_packet; ++ struct arphdr *arp_header; + grub_net_link_level_address_t target_mac_addr; + grub_err_t err; + int i; + grub_uint8_t *nbd; + grub_uint8_t arp_data[128]; ++ grub_uint8_t hln; ++ grub_uint8_t pln; ++ grub_uint8_t arp_packet_len; ++ grub_uint8_t *tmp_ptr; + + if (proto_addr->type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) + return grub_error (GRUB_ERR_BUG, "unsupported address family"); +@@ -73,25 +67,39 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf, + grub_netbuff_clear (&nb); + grub_netbuff_reserve (&nb, 128); + +- err = grub_netbuff_push (&nb, sizeof (*arp_packet)); ++ hln = inf->card->default_address.len; ++ pln = sizeof (proto_addr->ipv4); ++ arp_packet_len = sizeof (*arp_header) + 2 * (hln + pln); ++ ++ err = grub_netbuff_push (&nb, arp_packet_len); + if (err) + return err; + +- arp_packet = (struct arppkt *) nb.data; +- arp_packet->hrd = grub_cpu_to_be16_compile_time (GRUB_NET_ARPHRD_ETHERNET); +- arp_packet->hln = 6; +- arp_packet->pro = grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP); +- arp_packet->pln = 4; +- arp_packet->op = grub_cpu_to_be16_compile_time (ARP_REQUEST); +- /* Sender hardware address. */ +- grub_memcpy (aux, &inf->hwaddress.mac, 6); +- +- grub_memcpy (arp_packet->sender_mac, &inf->hwaddress.mac, 6); +- arp_packet->sender_ip = inf->address.ipv4; +- grub_memset (arp_packet->recv_mac, 0, 6); +- arp_packet->recv_ip = proto_addr->ipv4; +- /* Target protocol address */ +- grub_memset (&target_mac_addr.mac, 0xff, 6); ++ arp_header = (struct arphdr *) nb.data; ++ arp_header->hrd = grub_cpu_to_be16 (inf->card->default_address.type); ++ arp_header->hln = hln; ++ arp_header->pro = grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP); ++ arp_header->pln = pln; ++ arp_header->op = grub_cpu_to_be16_compile_time (ARP_REQUEST); ++ tmp_ptr = nb.data + sizeof (*arp_header); ++ ++ /* The source hardware address. */ ++ grub_memcpy (tmp_ptr, inf->hwaddress.mac, hln); ++ tmp_ptr += hln; ++ ++ /* The source protocol address. */ ++ grub_memcpy (tmp_ptr, &inf->address.ipv4, pln); ++ tmp_ptr += pln; ++ ++ /* The target hardware address. */ ++ grub_memset (tmp_ptr, 0, hln); ++ tmp_ptr += hln; ++ ++ /* The target protocol address */ ++ grub_memcpy (tmp_ptr, &proto_addr->ipv4, pln); ++ tmp_ptr += pln; ++ ++ grub_memset (&target_mac_addr.mac, 0xff, hln); + + nbd = nb.data; + send_ethernet_packet (inf, &nb, target_mac_addr, GRUB_NET_ETHERTYPE_ARP); +@@ -116,37 +124,62 @@ grub_err_t + grub_net_arp_receive (struct grub_net_buff *nb, + struct grub_net_card *card) + { +- struct arppkt *arp_packet = (struct arppkt *) nb->data; ++ struct arphdr *arp_header = (struct arphdr *) nb->data; + grub_net_network_level_address_t sender_addr, target_addr; + grub_net_link_level_address_t sender_mac_addr; + struct grub_net_network_level_interface *inf; ++ grub_uint16_t hw_type; ++ grub_uint8_t hln; ++ grub_uint8_t pln; ++ grub_uint8_t arp_packet_len; ++ grub_uint8_t *tmp_ptr; + +- if (arp_packet->pro != grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP) +- || arp_packet->pln != 4 || arp_packet->hln != 6 +- || nb->tail - nb->data < (int) sizeof (*arp_packet)) ++ hw_type = card->default_address.type; ++ hln = card->default_address.len; ++ pln = sizeof(sender_addr.ipv4); ++ arp_packet_len = sizeof (*arp_header) + 2 * (pln + hln); ++ ++ if (arp_header->pro != grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP) ++ || arp_header->hrd != grub_cpu_to_be16 (hw_type) ++ || arp_header->hln != hln || arp_header->pln != pln ++ || nb->tail - nb->data < (int) arp_packet_len) { + return GRUB_ERR_NONE; ++ } + ++ tmp_ptr = nb->data + sizeof (*arp_header); ++ ++ /* The source hardware address. */ ++ sender_mac_addr.type = hw_type; ++ sender_mac_addr.len = hln; ++ grub_memcpy (sender_mac_addr.mac, tmp_ptr, hln); ++ tmp_ptr += hln; ++ ++ /* The source protocol address. */ + sender_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; ++ grub_memcpy(&sender_addr.ipv4, tmp_ptr, pln); ++ tmp_ptr += pln; ++ ++ grub_net_link_layer_add_address (card, &sender_addr, &sender_mac_addr, 1); ++ ++ /* The target hardware address. */ ++ tmp_ptr += hln; ++ ++ /* The target protocol address. */ + target_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; +- sender_addr.ipv4 = arp_packet->sender_ip; +- target_addr.ipv4 = arp_packet->recv_ip; +- if (arp_packet->sender_ip == pending_req) ++ grub_memcpy(&target_addr.ipv4, tmp_ptr, pln); ++ ++ if (sender_addr.ipv4 == pending_req) + have_pending = 1; + +- sender_mac_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; +- grub_memcpy (sender_mac_addr.mac, arp_packet->sender_mac, +- sizeof (sender_mac_addr.mac)); +- grub_net_link_layer_add_address (card, &sender_addr, &sender_mac_addr, 1); +- + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + { + /* Am I the protocol address target? */ + if (grub_net_addr_cmp (&inf->address, &target_addr) == 0 +- && arp_packet->op == grub_cpu_to_be16_compile_time (ARP_REQUEST)) ++ && arp_header->op == grub_cpu_to_be16_compile_time (ARP_REQUEST)) + { + grub_net_link_level_address_t target; + struct grub_net_buff nb_reply; +- struct arppkt *arp_reply; ++ struct arphdr *arp_reply; + grub_uint8_t arp_data[128]; + grub_err_t err; + +@@ -155,25 +188,39 @@ grub_net_arp_receive (struct grub_net_buff *nb, + grub_netbuff_clear (&nb_reply); + grub_netbuff_reserve (&nb_reply, 128); + +- err = grub_netbuff_push (&nb_reply, sizeof (*arp_packet)); ++ err = grub_netbuff_push (&nb_reply, arp_packet_len); + if (err) + return err; + +- arp_reply = (struct arppkt *) nb_reply.data; ++ arp_reply = (struct arphdr *) nb_reply.data; + +- arp_reply->hrd = grub_cpu_to_be16_compile_time (GRUB_NET_ARPHRD_ETHERNET); ++ arp_reply->hrd = grub_cpu_to_be16 (hw_type); + arp_reply->pro = grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP); +- arp_reply->pln = 4; +- arp_reply->hln = 6; ++ arp_reply->pln = pln; ++ arp_reply->hln = hln; + arp_reply->op = grub_cpu_to_be16_compile_time (ARP_REPLY); +- arp_reply->sender_ip = arp_packet->recv_ip; +- arp_reply->recv_ip = arp_packet->sender_ip; +- arp_reply->hln = 6; +- +- target.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; +- grub_memcpy (target.mac, arp_packet->sender_mac, 6); +- grub_memcpy (arp_reply->sender_mac, inf->hwaddress.mac, 6); +- grub_memcpy (arp_reply->recv_mac, arp_packet->sender_mac, 6); ++ ++ tmp_ptr = nb_reply.data + sizeof (*arp_reply); ++ ++ /* The source hardware address. */ ++ grub_memcpy (tmp_ptr, inf->hwaddress.mac, hln); ++ tmp_ptr += hln; ++ ++ /* The source protocol address. */ ++ grub_memcpy (tmp_ptr, &target_addr.ipv4, pln); ++ tmp_ptr += pln; ++ ++ /* The target hardware address. */ ++ grub_memcpy (tmp_ptr, sender_mac_addr.mac, hln); ++ tmp_ptr += hln; ++ ++ /* The target protocol address */ ++ grub_memcpy (tmp_ptr, &sender_addr.ipv4, pln); ++ tmp_ptr += pln; ++ ++ target.type = hw_type; ++ target.len = hln; ++ grub_memcpy (target.mac, sender_mac_addr.mac, hln); + + /* Change operation to REPLY and send packet */ + send_ethernet_packet (inf, &nb_reply, target, GRUB_NET_ETHERTYPE_ARP); +diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c +index dfdf7e08d90..0a2d11b8820 100644 +--- a/grub-core/net/bootp.c ++++ b/grub-core/net/bootp.c +@@ -219,7 +219,6 @@ grub_net_configure_by_dhcp_ack (const char *name, + int is_def, char **device, char **path) + { + grub_net_network_level_address_t addr; +- grub_net_link_level_address_t hwaddr; + struct grub_net_network_level_interface *inter; + int mask = -1; + +@@ -231,12 +230,8 @@ grub_net_configure_by_dhcp_ack (const char *name, + if (path) + *path = 0; + +- grub_memcpy (hwaddr.mac, bp->mac_addr, +- bp->hw_len < sizeof (hwaddr.mac) ? bp->hw_len +- : sizeof (hwaddr.mac)); +- hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; +- +- inter = grub_net_add_addr (name, card, &addr, &hwaddr, flags); ++ grub_dprintf("dhcp", "configuring dhcp for %s\n", name); ++ inter = grub_net_add_addr (name, card, &addr, &card->default_address, flags); + if (!inter) + return 0; + +@@ -762,7 +757,8 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), + grub_memset (pack, 0, sizeof (*pack) + 64); + pack->opcode = 1; + pack->hw_type = 1; +- pack->hw_len = 6; ++ pack->hw_len = ifaces[j].hwaddress.len > 16 ? 0 ++ : ifaces[j].hwaddress.len; + err = grub_get_datetime (&date); + if (err || !grub_datetime2unixtime (&date, &t)) + { +@@ -773,7 +769,7 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), + ifaces[j].dhcp_xid = pack->xid; + pack->seconds = grub_cpu_to_be16 (t); + +- grub_memcpy (&pack->mac_addr, &ifaces[j].hwaddress.mac, 6); ++ grub_memcpy (&pack->mac_addr, &ifaces[j].hwaddress.mac, pack->hw_len); + + grub_netbuff_push (nb, sizeof (*udph)); + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index 69b0fc7a8fe..b9ed13fcad1 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -290,6 +290,9 @@ grub_efinet_findcards (void) + /* This should not happen... Why? */ + continue; + ++ if (net->mode->hwaddr_size > GRUB_NET_MAX_LINK_ADDRESS_SIZE) ++ continue; ++ + if (net->mode->state == GRUB_EFI_NETWORK_STOPPED + && efi_call_1 (net->start, net) != GRUB_EFI_SUCCESS) + continue; +@@ -326,10 +329,11 @@ grub_efinet_findcards (void) + card->name = grub_xasprintf ("efinet%d", i++); + card->driver = &efidriver; + card->flags = 0; +- card->default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; ++ card->default_address.type = net->mode->if_type; ++ card->default_address.len = net->mode->hwaddr_size; + grub_memcpy (card->default_address.mac, + net->mode->current_address, +- sizeof (card->default_address.mac)); ++ net->mode->hwaddr_size); + card->efi_net = net; + card->efi_handle = *handle; + +diff --git a/grub-core/net/drivers/emu/emunet.c b/grub-core/net/drivers/emu/emunet.c +index 7c977cd52ca..962b0c86d2b 100644 +--- a/grub-core/net/drivers/emu/emunet.c ++++ b/grub-core/net/drivers/emu/emunet.c +@@ -46,6 +46,7 @@ static struct grub_net_card emucard = + .mtu = 1500, + .default_address = { + .type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET, ++ . len = 6, + {.mac = {0, 1, 2, 3, 4, 5}} + }, + .flags = 0 +diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c +index e8c0b22e294..5660149503d 100644 +--- a/grub-core/net/drivers/i386/pc/pxe.c ++++ b/grub-core/net/drivers/i386/pc/pxe.c +@@ -387,20 +387,21 @@ GRUB_MOD_INIT(pxe) + grub_memset (ui, 0, sizeof (*ui)); + grub_pxe_call (GRUB_PXENV_UNDI_GET_INFORMATION, ui, pxe_rm_entry); + ++ grub_pxe_card.default_address.len = 6; + grub_memcpy (grub_pxe_card.default_address.mac, ui->current_addr, +- sizeof (grub_pxe_card.default_address.mac)); +- for (i = 0; i < sizeof (grub_pxe_card.default_address.mac); i++) ++ grub_pxe_card.default_address.len); ++ for (i = 0; i < grub_pxe_card.default_address.len; i++) + if (grub_pxe_card.default_address.mac[i] != 0) + break; +- if (i != sizeof (grub_pxe_card.default_address.mac)) ++ if (i != grub_pxe_card.default_address.len) + { +- for (i = 0; i < sizeof (grub_pxe_card.default_address.mac); i++) ++ for (i = 0; i < grub_pxe_card.default_address.len; i++) + if (grub_pxe_card.default_address.mac[i] != 0xff) + break; + } +- if (i == sizeof (grub_pxe_card.default_address.mac)) ++ if (i == grub_pxe_card.default_address.len) + grub_memcpy (grub_pxe_card.default_address.mac, ui->permanent_addr, +- sizeof (grub_pxe_card.default_address.mac)); ++ grub_pxe_card.default_address.len); + grub_pxe_card.mtu = ui->mtu; + + grub_pxe_card.default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; +diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c +index cd24ddc99c5..5a199bcaa75 100644 +--- a/grub-core/net/drivers/ieee1275/ofnet.c ++++ b/grub-core/net/drivers/ieee1275/ofnet.c +@@ -154,6 +154,7 @@ grub_ieee1275_parse_bootpath (const char *devpath, char *bootpath, + struct grub_net_network_level_interface *inter; + + hw_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; ++ hw_addr.len = 6; + + args = bootpath + grub_strlen (devpath) + 1; + do +@@ -369,6 +370,7 @@ search_net_devices (struct grub_ieee1275_devalias *alias) + grub_memcpy (&lla.mac, pprop, 6); + + lla.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; ++ lla.len = 6; + card->default_address = lla; + + card->txbufsize = ALIGN_UP (card->mtu, 64) + 256; +diff --git a/grub-core/net/drivers/uboot/ubootnet.c b/grub-core/net/drivers/uboot/ubootnet.c +index 056052e40d5..22ebcbf211e 100644 +--- a/grub-core/net/drivers/uboot/ubootnet.c ++++ b/grub-core/net/drivers/uboot/ubootnet.c +@@ -131,6 +131,7 @@ GRUB_MOD_INIT (ubootnet) + + grub_memcpy (&(card->default_address.mac), &devinfo->di_net.hwaddr, 6); + card->default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; ++ card->default_address.len = 6; + + card->txbufsize = ALIGN_UP (card->mtu, 64) + 256; + card->txbuf = grub_zalloc (card->txbufsize); +diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c +index faaca67c50e..1b479d3cadc 100644 +--- a/grub-core/net/ethernet.c ++++ b/grub-core/net/ethernet.c +@@ -29,13 +29,6 @@ + + #define LLCADDRMASK 0x7f + +-struct etherhdr +-{ +- grub_uint8_t dst[6]; +- grub_uint8_t src[6]; +- grub_uint16_t type; +-} GRUB_PACKED; +- + struct llchdr + { + grub_uint8_t dsap; +@@ -55,13 +48,15 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, + grub_net_link_level_address_t target_addr, + grub_net_ethertype_t ethertype) + { +- struct etherhdr *eth; ++ grub_uint8_t *eth; + grub_err_t err; + grub_uint32_t vlantag = 0; +- grub_uint8_t etherhdr_size; ++ grub_uint8_t hw_addr_len = inf->card->default_address.len; ++ grub_uint8_t etherhdr_size = 2 * hw_addr_len + 2; + +- etherhdr_size = sizeof (*eth); +- COMPILE_TIME_ASSERT (sizeof (*eth) + 4 < GRUB_NET_MAX_LINK_HEADER_SIZE); ++ /* Source and destination link addresses + ethertype + vlan tag */ ++ COMPILE_TIME_ASSERT ((GRUB_NET_MAX_LINK_ADDRESS_SIZE * 2 + 2 + 4) < ++ GRUB_NET_MAX_LINK_HEADER_SIZE); + + const char *vlantag_text = grub_env_get ("vlan-tag"); + if (vlantag_text != 0) { +@@ -72,11 +67,22 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, + err = grub_netbuff_push (nb, etherhdr_size); + if (err) + return err; +- eth = (struct etherhdr *) nb->data; +- grub_memcpy (eth->dst, target_addr.mac, 6); +- grub_memcpy (eth->src, inf->hwaddress.mac, 6); ++ eth = nb->data; ++ grub_memcpy (eth, target_addr.mac, hw_addr_len); ++ eth += hw_addr_len; ++ grub_memcpy (eth, inf->hwaddress.mac, hw_addr_len); ++ eth += hw_addr_len; ++ ++ /* Check if a vlan-tag is present. */ ++ if (vlantag != 0) ++ { ++ *((grub_uint32_t *)eth) = grub_cpu_to_be32 (vlantag); ++ eth += sizeof (vlantag); ++ } ++ ++ /* Write ethertype */ ++ *((grub_uint16_t*) eth) = grub_cpu_to_be16 (ethertype); + +- eth->type = grub_cpu_to_be16 (ethertype); + if (!inf->card->opened) + { + err = GRUB_ERR_NONE; +@@ -87,18 +93,6 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, + inf->card->opened = 1; + } + +- /* Check if a vlan-tag is needed. */ +- if (vlantag != 0) +- { +- /* Move eth type to the right */ +- grub_memcpy((char *) nb->data + etherhdr_size - 2, +- (char *) nb->data + etherhdr_size - 6, 2); +- +- /* Add the tag in the middle */ +- grub_memcpy((char *) nb->data + etherhdr_size - 6, +- &vlantag, 4); +- } +- + return inf->card->driver->send (inf->card, nb); + } + +@@ -106,29 +100,37 @@ grub_err_t + grub_net_recv_ethernet_packet (struct grub_net_buff *nb, + struct grub_net_card *card) + { +- struct etherhdr *eth; ++ grub_uint8_t *eth; + struct llchdr *llch; + struct snaphdr *snaph; + grub_net_ethertype_t type; + grub_net_link_level_address_t hwaddress; + grub_net_link_level_address_t src_hwaddress; + grub_err_t err; +- grub_uint8_t etherhdr_size = sizeof (*eth); ++ grub_uint8_t hw_addr_len = card->default_address.len; ++ grub_uint8_t etherhdr_size = 2 * hw_addr_len + 2; + +- grub_uint16_t vlantag_identifier = 0; +- grub_memcpy (&vlantag_identifier, nb->data + etherhdr_size - 2, 2); ++ eth = nb->data; + +- /* Check if a vlan-tag is present. */ +- if (vlantag_identifier == VLANTAG_IDENTIFIER) ++ hwaddress.type = card->default_address.type; ++ hwaddress.len = hw_addr_len; ++ grub_memcpy (hwaddress.mac, eth, hw_addr_len); ++ eth += hw_addr_len; ++ ++ src_hwaddress.type = card->default_address.type; ++ src_hwaddress.len = hw_addr_len; ++ grub_memcpy (src_hwaddress.mac, eth, hw_addr_len); ++ eth += hw_addr_len; ++ ++ type = grub_be_to_cpu16 (*(grub_uint16_t*)(eth)); ++ if (type == VLANTAG_IDENTIFIER) + { ++ /* Skip vlan tag */ + etherhdr_size += 4; +- /* Move eth type to the original position */ +- grub_memcpy((char *) nb->data + etherhdr_size - 6, +- (char *) nb->data + etherhdr_size - 2, 2); ++ eth += 4; ++ type = grub_be_to_cpu16 (*(grub_uint16_t*)(eth)); + } + +- eth = (struct etherhdr *) nb->data; +- type = grub_be_to_cpu16 (eth->type); + err = grub_netbuff_pull (nb, etherhdr_size); + if (err) + return err; +@@ -148,11 +150,6 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb, + } + } + +- hwaddress.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; +- grub_memcpy (hwaddress.mac, eth->dst, sizeof (hwaddress.mac)); +- src_hwaddress.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; +- grub_memcpy (src_hwaddress.mac, eth->src, sizeof (src_hwaddress.mac)); +- + switch (type) + { + /* ARP packet. */ +diff --git a/grub-core/net/icmp6.c b/grub-core/net/icmp6.c +index 7953e68ecfa..7e7a6bcbd68 100644 +--- a/grub-core/net/icmp6.c ++++ b/grub-core/net/icmp6.c +@@ -230,8 +230,9 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb, + && ohdr->len == 1) + { + grub_net_link_level_address_t ll_address; +- ll_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; +- grub_memcpy (ll_address.mac, ohdr + 1, sizeof (ll_address.mac)); ++ ll_address.type = card->default_address.type; ++ ll_address.len = card->default_address.len; ++ grub_memcpy (ll_address.mac, ohdr + 1, ll_address.len); + grub_net_link_layer_add_address (card, source, &ll_address, 0); + } + } +@@ -334,8 +335,9 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb, + && ohdr->len == 1) + { + grub_net_link_level_address_t ll_address; +- ll_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; +- grub_memcpy (ll_address.mac, ohdr + 1, sizeof (ll_address.mac)); ++ ll_address.type = card->default_address.type; ++ ll_address.len = card->default_address.len; ++ grub_memcpy (ll_address.mac, ohdr + 1, ll_address.len); + grub_net_link_layer_add_address (card, source, &ll_address, 0); + } + } +@@ -366,8 +368,9 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb, + && ohdr->len == 1) + { + grub_net_link_level_address_t ll_address; +- ll_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; +- grub_memcpy (ll_address.mac, ohdr + 1, sizeof (ll_address.mac)); ++ ll_address.type = card->default_address.type; ++ ll_address.len = card->default_address.len; ++ grub_memcpy (ll_address.mac, ohdr + 1, ll_address.len); + grub_net_link_layer_add_address (card, source, &ll_address, 0); + } + if (ohdr->type == OPTION_PREFIX && ohdr->len == 4) +diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c +index 9e7930caa03..311213feec1 100644 +--- a/grub-core/net/ip.c ++++ b/grub-core/net/ip.c +@@ -273,8 +273,8 @@ handle_dgram (struct grub_net_buff *nb, + && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV + && inf->dhcp_xid == bootp->xid + && inf->hwaddress.type == GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET +- && grub_memcmp (inf->hwaddress.mac, &bootp->mac_addr, +- sizeof (inf->hwaddress.mac)) == 0) ++ && (grub_memcmp (inf->hwaddress.mac, &bootp->mac_addr, ++ bootp->hw_len) == 0 || bootp->hw_len == 0)) + { + grub_net_process_dhcp (nb, inf->card); + grub_netbuff_free (nb); +diff --git a/grub-core/net/net.c b/grub-core/net/net.c +index fc6f714bf7f..b3a80ba2954 100644 +--- a/grub-core/net/net.c ++++ b/grub-core/net/net.c +@@ -143,8 +143,9 @@ grub_net_link_layer_resolve (struct grub_net_network_level_interface *inf, + << 48) + && proto_addr->ipv6[1] == (grub_be_to_cpu64_compile_time (1)))) + { +- hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; +- grub_memset (hw_addr->mac, -1, 6); ++ hw_addr->type = inf->card->default_address.type; ++ hw_addr->len = inf->card->default_address.len; ++ grub_memset (hw_addr->mac, -1, hw_addr->len); + return GRUB_ERR_NONE; + } + +@@ -152,6 +153,7 @@ grub_net_link_layer_resolve (struct grub_net_network_level_interface *inf, + && ((grub_be_to_cpu64 (proto_addr->ipv6[0]) >> 56) == 0xff)) + { + hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; ++ hw_addr->len = inf->card->default_address.len; + hw_addr->mac[0] = 0x33; + hw_addr->mac[1] = 0x33; + hw_addr->mac[2] = ((grub_be_to_cpu64 (proto_addr->ipv6[1]) >> 24) & 0xff); +@@ -771,23 +773,21 @@ grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf) + void + grub_net_hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str) + { +- str[0] = 0; +- switch (addr->type) ++ char *ptr; ++ unsigned i; ++ ++ if (addr->len > GRUB_NET_MAX_LINK_ADDRESS_SIZE) + { +- case GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET: +- { +- char *ptr; +- unsigned i; +- for (ptr = str, i = 0; i < ARRAY_SIZE (addr->mac); i++) +- { +- grub_snprintf (ptr, GRUB_NET_MAX_STR_HWADDR_LEN - (ptr - str), +- "%02x:", addr->mac[i] & 0xff); +- ptr += (sizeof ("XX:") - 1); +- } +- return; +- } ++ str[0] = 0; ++ grub_printf (_("Unsupported hw address type %d len %d\n"), ++ addr->type, addr->len); ++ return; ++ } ++ for (ptr = str, i = 0; i < addr->len; i++) ++ { ++ ptr += grub_snprintf (ptr, GRUB_NET_MAX_STR_HWADDR_LEN - (ptr - str), ++ "%02x:", addr->mac[i] & 0xff); + } +- grub_printf (_("Unsupported hw address type %d\n"), addr->type); + } + + int +@@ -798,13 +798,17 @@ grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a, + return -1; + if (a->type > b->type) + return +1; +- switch (a->type) ++ if (a->len < b->len) ++ return -1; ++ if (a->len > b->len) ++ return +1; ++ if (a->len > GRUB_NET_MAX_LINK_ADDRESS_SIZE) + { +- case GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET: +- return grub_memcmp (a->mac, b->mac, sizeof (a->mac)); ++ grub_printf (_("Unsupported hw address type %d len %d\n"), ++ a->type, a->len); ++ return + 1; + } +- grub_printf (_("Unsupported hw address type %d\n"), a->type); +- return 1; ++ return grub_memcmp (a->mac, b->mac, a->len); + } + + int +diff --git a/include/grub/net.h b/include/grub/net.h +index b1bc23048f1..0d9213d6759 100644 +--- a/include/grub/net.h ++++ b/include/grub/net.h +@@ -29,7 +29,8 @@ + + enum + { +- GRUB_NET_MAX_LINK_HEADER_SIZE = 64, ++ GRUB_NET_MAX_LINK_HEADER_SIZE = 96, ++ GRUB_NET_MAX_LINK_ADDRESS_SIZE = 32, + GRUB_NET_UDP_HEADER_SIZE = 8, + GRUB_NET_TCP_HEADER_SIZE = 20, + GRUB_NET_OUR_IPV4_HEADER_SIZE = 20, +@@ -42,15 +43,17 @@ enum + + typedef enum grub_link_level_protocol_id + { +- GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET ++ /* IANA ARP constant to define hardware type. */ ++ GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET = 1, + } grub_link_level_protocol_id_t; + + typedef struct grub_net_link_level_address + { + grub_link_level_protocol_id_t type; ++ grub_uint8_t len; + union + { +- grub_uint8_t mac[6]; ++ grub_uint8_t mac[GRUB_NET_MAX_LINK_ADDRESS_SIZE]; + }; + } grub_net_link_level_address_t; + +@@ -531,11 +534,13 @@ grub_net_addr_cmp (const grub_net_network_level_address_t *a, + #define GRUB_NET_MAX_STR_ADDR_LEN sizeof ("XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX") + + /* +- Currently suppoerted adresses: +- ethernet: XX:XX:XX:XX:XX:XX ++ Up to 32 byte hardware address supported, see GRUB_NET_MAX_LINK_ADDRESS_SIZE + */ +- +-#define GRUB_NET_MAX_STR_HWADDR_LEN (sizeof ("XX:XX:XX:XX:XX:XX")) ++#define GRUB_NET_MAX_STR_HWADDR_LEN (sizeof (\ ++ "XX:XX:XX:XX:XX:XX:XX:XX:"\ ++ "XX:XX:XX:XX:XX:XX:XX:XX:"\ ++ "XX:XX:XX:XX:XX:XX:XX:XX:"\ ++ "XX:XX:XX:XX:XX:XX:XX:XX")) + + void + grub_net_addr_to_str (const grub_net_network_level_address_t *target, diff --git a/SOURCES/0249-misc-fix-invalid-character-recongition-in-strto-l.patch b/SOURCES/0249-misc-fix-invalid-character-recongition-in-strto-l.patch new file mode 100644 index 0000000..51feac7 --- /dev/null +++ b/SOURCES/0249-misc-fix-invalid-character-recongition-in-strto-l.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aaron Miller +Date: Fri, 29 Jul 2016 17:41:27 +0800 +Subject: [PATCH] misc: fix invalid character recongition in strto*l + +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 240396c55f3..d0ca2ee603b 100644 +--- a/grub-core/kern/misc.c ++++ b/grub-core/kern/misc.c +@@ -436,9 +436,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; + diff --git a/SOURCES/0250-net-read-bracketed-ipv6-addrs-and-port-numbers.patch b/SOURCES/0250-net-read-bracketed-ipv6-addrs-and-port-numbers.patch new file mode 100644 index 0000000..5b10e5d --- /dev/null +++ b/SOURCES/0250-net-read-bracketed-ipv6-addrs-and-port-numbers.patch @@ -0,0 +1,230 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aaron Miller +Date: Fri, 29 Jul 2016 17:41:38 +0800 +Subject: [PATCH] net: read bracketed ipv6 addrs and port numbers + +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 | 23 ++++++++++++---- + grub-core/net/net.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + grub-core/net/tftp.c | 8 ++++-- + include/grub/net.h | 1 + + 4 files changed, 102 insertions(+), 7 deletions(-) + +diff --git a/grub-core/net/http.c b/grub-core/net/http.c +index ef9538c539c..6d99051d345 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") +@@ -391,9 +402,11 @@ 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, +- http_err, NULL, ++ 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 b3a80ba2954..b062f6fd0cd 100644 +--- a/grub-core/net/net.c ++++ b/grub-core/net/net.c +@@ -462,6 +462,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; +@@ -500,6 +506,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; +@@ -1348,8 +1357,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) + { +@@ -1387,6 +1398,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) +diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c +index 3931884c6dd..d13a6c8ed2d 100644 +--- a/grub-core/net/tftp.c ++++ b/grub-core/net/tftp.c +@@ -333,6 +333,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) +@@ -396,14 +397,17 @@ tftp_open (struct grub_file *file, const char *filename) + err = grub_net_resolve_address (file->device->net->server, &addr); + if (err) + { +- grub_dprintf("tftp", "Address resolution failed: %d\n", err); ++ grub_dprintf ("tftp", "Address resolution failed: %d\n", 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); + return err; + } + + grub_dprintf("tftp", "opening connection\n"); + 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 0d9213d6759..20e699bb025 100644 +--- a/include/grub/net.h ++++ b/include/grub/net.h +@@ -261,6 +261,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; diff --git a/SOURCES/0251-net-read-bracketed-ipv6-addrs-and-port-numbers-pjone.patch b/SOURCES/0251-net-read-bracketed-ipv6-addrs-and-port-numbers-pjone.patch new file mode 100644 index 0000000..b8a71b6 --- /dev/null +++ b/SOURCES/0251-net-read-bracketed-ipv6-addrs-and-port-numbers-pjone.patch @@ -0,0 +1,183 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aaron Miller +Date: Fri, 29 Jul 2016 17:41:38 +0800 +Subject: [PATCH] net: read bracketed ipv6 addrs and port numbers (pjones + fixup) + +Various bug fixes related to previous patch. + +Signed-off-by: Peter Jones +--- + grub-core/net/http.c | 6 ++++-- + grub-core/net/net.c | 31 +++++++++++++------------------ + grub-core/net/tftp.c | 19 ++++++++++++++++--- + 3 files changed, 33 insertions(+), 23 deletions(-) + +diff --git a/grub-core/net/http.c b/grub-core/net/http.c +index 6d99051d345..2b46e4672fc 100644 +--- a/grub-core/net/http.c ++++ b/grub-core/net/http.c +@@ -289,7 +289,9 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)), + nb2 = grub_netbuff_alloc (data->chunk_rem); + if (!nb2) + return grub_errno; +- grub_netbuff_put (nb2, data->chunk_rem); ++ err = grub_netbuff_put (nb2, data->chunk_rem); ++ if (err) ++ return grub_errno; + grub_memcpy (nb2->data, nb->data, data->chunk_rem); + if (file->device->net->packs.count >= 20) + { +@@ -406,7 +408,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial) + data->filename, server, port ? port : HTTP_PORT); + data->sock = grub_net_tcp_open (server, + port ? port : HTTP_PORT, http_receive, +- http_err, http_err, ++ http_err, NULL, + file); + if (!data->sock) + { +diff --git a/grub-core/net/net.c b/grub-core/net/net.c +index b062f6fd0cd..6b4b10ba444 100644 +--- a/grub-core/net/net.c ++++ b/grub-core/net/net.c +@@ -464,10 +464,11 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest) + int word, quaddot = -1; + int bracketed = 0; + +- if (ptr[0] == '[') { +- bracketed = 1; +- ptr++; +- } ++ if (ptr[0] == '[') ++ { ++ bracketed = 1; ++ ptr++; ++ } + + if (ptr[0] == ':' && ptr[1] != ':') + return 0; +@@ -506,9 +507,8 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest) + grub_memset (&newip[quaddot], 0, (7 - word) * sizeof (newip[0])); + } + grub_memcpy (ip, newip, 16); +- if (bracketed && *ptr == ']') { ++ if (bracketed && *ptr == ']') + ptr++; +- } + if (rest) + *rest = ptr; + return 1; +@@ -1401,7 +1401,7 @@ grub_net_open_real (const char *name) + char* port_start; + /* ipv6 or port specified? */ + if ((port_start = grub_strchr (server, ':'))) +- { ++ { + char* ipv6_begin; + if((ipv6_begin = grub_strchr (server, '['))) + { +@@ -1473,19 +1473,13 @@ grub_net_open_real (const char *name) + { + grub_net_t ret = grub_zalloc (sizeof (*ret)); + if (!ret) +- return NULL; +- ret->protocol = proto; +- if (server) + { +- ret->server = grub_strdup (server); +- if (!ret->server) +- { +- grub_free (ret); +- return NULL; +- } ++ grub_free (host); ++ return NULL; + } +- else +- ret->server = NULL; ++ ret->protocol = proto; ++ ret->port = port; ++ ret->server = host; + ret->fs = &grub_net_fs; + ret->offset = 0; + ret->eof = 0; +@@ -1516,6 +1510,7 @@ grub_net_open_real (const char *name) + grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("disk `%s' not found"), + name); + ++ grub_free (host); + return NULL; + } + +diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c +index d13a6c8ed2d..17583cba380 100644 +--- a/grub-core/net/tftp.c ++++ b/grub-core/net/tftp.c +@@ -346,7 +346,10 @@ tftp_open (struct grub_file *file, const char *filename) + grub_netbuff_reserve (&nb, 1500); + err = grub_netbuff_push (&nb, sizeof (*tftph)); + if (err) +- return err; ++ { ++ grub_free (data); ++ return err; ++ } + + tftph = (struct tftphdr *) nb.data; + +@@ -384,14 +387,20 @@ tftp_open (struct grub_file *file, const char *filename) + + err = grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen)); + if (err) +- return err; ++ { ++ grub_free (data); ++ return err; ++ } + + file->not_easily_seekable = 1; + file->data = data; + + data->pq = grub_priority_queue_new (sizeof (struct grub_net_buff *), cmp); + if (!data->pq) +- return grub_errno; ++ { ++ grub_free (data); ++ return grub_errno; ++ } + + grub_dprintf("tftp", "resolving address for %s\n", file->device->net->server); + err = grub_net_resolve_address (file->device->net->server, &addr); +@@ -402,6 +411,7 @@ tftp_open (struct grub_file *file, const char *filename) + (unsigned long long)data->file_size, + (unsigned long long)data->block_size); + destroy_pq (data); ++ grub_free (data); + return err; + } + +@@ -413,6 +423,7 @@ tftp_open (struct grub_file *file, const char *filename) + { + grub_dprintf("tftp", "connection failed\n"); + destroy_pq (data); ++ grub_free (data); + return grub_errno; + } + +@@ -426,6 +437,7 @@ tftp_open (struct grub_file *file, const char *filename) + { + grub_net_udp_close (data->sock); + destroy_pq (data); ++ grub_free (data); + return err; + } + grub_net_poll_cards (GRUB_NET_INTERVAL + (i * GRUB_NET_INTERVAL_ADDITION), +@@ -442,6 +454,7 @@ tftp_open (struct grub_file *file, const char *filename) + { + grub_net_udp_close (data->sock); + destroy_pq (data); ++ grub_free (data); + return grub_errno; + } + diff --git a/SOURCES/0252-tftp-Fix-a-minor-const-error.patch b/SOURCES/0252-tftp-Fix-a-minor-const-error.patch new file mode 100644 index 0000000..eb6abd9 --- /dev/null +++ b/SOURCES/0252-tftp-Fix-a-minor-const-error.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 21 Jun 2018 19:09:11 -0400 +Subject: [PATCH] tftp: Fix a minor const error + +Signed-off-by: Peter Jones +--- + grub-core/net/tftp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c +index 17583cba380..e267af354f4 100644 +--- a/grub-core/net/tftp.c ++++ b/grub-core/net/tftp.c +@@ -307,7 +307,7 @@ static void + grub_normalize_filename (char *normalized, const char *filename) + { + char *dest = normalized; +- char *src = filename; ++ const char *src = filename; + + while (*src != '\0') + { diff --git a/SOURCES/0253-bootp-New-net_bootp6-command.patch b/SOURCES/0253-bootp-New-net_bootp6-command.patch new file mode 100644 index 0000000..5cfc9cf --- /dev/null +++ b/SOURCES/0253-bootp-New-net_bootp6-command.patch @@ -0,0 +1,1304 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Sun, 10 Jul 2016 23:46:06 +0800 +Subject: [PATCH] bootp: New net_bootp6 command + +Implement new net_bootp6 command for IPv6 network auto configuration via the +DHCPv6 protocol (RFC3315). + +Signed-off-by: Michael Chang +Signed-off-by: Ken Lin +--- + grub-core/net/bootp.c | 1048 +++++++++++++++++++++++++++++++++++++++++-------- + grub-core/net/ip.c | 39 ++ + include/grub/net.h | 91 +++-- + 3 files changed, 985 insertions(+), 193 deletions(-) + +diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c +index 0a2d11b8820..26b3d83d0bc 100644 +--- a/grub-core/net/bootp.c ++++ b/grub-core/net/bootp.c +@@ -25,6 +25,98 @@ + #include + #include + #include ++#include ++#include ++ ++static int ++dissect_url (const char *url, char **proto, char **host, char **path) ++{ ++ const char *p, *ps; ++ grub_size_t l; ++ ++ *proto = *host = *path = NULL; ++ ps = p = url; ++ ++ while ((p = grub_strchr (p, ':'))) ++ { ++ if (grub_strlen (p) < sizeof ("://") - 1) ++ break; ++ if (grub_memcmp (p, "://", sizeof ("://") - 1) == 0) ++ { ++ l = p - ps; ++ *proto = grub_malloc (l + 1); ++ if (!*proto) ++ { ++ grub_print_error (); ++ return 0; ++ } ++ ++ grub_memcpy (*proto, ps, l); ++ (*proto)[l] = '\0'; ++ p += sizeof ("://") - 1; ++ break; ++ } ++ ++p; ++ } ++ ++ if (!*proto) ++ { ++ grub_dprintf ("bootp", "url: %s is not valid, protocol not found\n", url); ++ return 0; ++ } ++ ++ ps = p; ++ p = grub_strchr (p, '/'); ++ ++ if (!p) ++ { ++ grub_dprintf ("bootp", "url: %s is not valid, host/path not found\n", url); ++ grub_free (*proto); ++ *proto = NULL; ++ return 0; ++ } ++ ++ l = p - ps; ++ ++ if (l > 2 && ps[0] == '[' && ps[l - 1] == ']') ++ { ++ *host = grub_malloc (l - 1); ++ if (!*host) ++ { ++ grub_print_error (); ++ grub_free (*proto); ++ *proto = NULL; ++ return 0; ++ } ++ grub_memcpy (*host, ps + 1, l - 2); ++ (*host)[l - 2] = 0; ++ } ++ else ++ { ++ *host = grub_malloc (l + 1); ++ if (!*host) ++ { ++ grub_print_error (); ++ grub_free (*proto); ++ *proto = NULL; ++ return 0; ++ } ++ grub_memcpy (*host, ps, l); ++ (*host)[l] = 0; ++ } ++ ++ *path = grub_strdup (p); ++ if (!*path) ++ { ++ grub_print_error (); ++ grub_free (*host); ++ grub_free (*proto); ++ *host = NULL; ++ *proto = NULL; ++ return 0; ++ } ++ return 1; ++} + + static char * + grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)), +@@ -341,178 +433,578 @@ grub_net_configure_by_dhcp_ack (const char *name, + return inter; + } + +-struct grub_net_network_level_interface * +-grub_net_configure_by_dhcpv6_ack (const char *name, +- struct grub_net_card *card, +- grub_net_interface_flags_t flags +- __attribute__((__unused__)), +- const grub_net_link_level_address_t *hwaddr, +- const struct grub_net_dhcpv6_packet *packet, +- int is_def, char **device, char **path) +-{ +- struct grub_net_network_level_interface *inter = NULL; +- struct grub_net_network_level_address addr; +- int mask = -1; +- +- if (!device || !path) ++/* The default netbuff size for sending DHCPv6 packets which should be ++ large enough to hold the information */ ++#define GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE 512 ++ ++struct grub_dhcp6_options ++{ ++ grub_uint8_t *client_duid; ++ grub_uint16_t client_duid_len; ++ grub_uint8_t *server_duid; ++ grub_uint16_t server_duid_len; ++ grub_uint32_t iaid; ++ grub_uint32_t t1; ++ grub_uint32_t t2; ++ grub_net_network_level_address_t *ia_addr; ++ grub_uint32_t preferred_lifetime; ++ grub_uint32_t valid_lifetime; ++ grub_net_network_level_address_t *dns_server_addrs; ++ grub_uint16_t num_dns_server; ++ char *boot_file_proto; ++ char *boot_file_server_ip; ++ char *boot_file_path; ++}; ++ ++typedef struct grub_dhcp6_options *grub_dhcp6_options_t; ++ ++struct grub_dhcp6_session ++{ ++ struct grub_dhcp6_session *next; ++ struct grub_dhcp6_session **prev; ++ grub_uint32_t iaid; ++ grub_uint32_t transaction_id:24; ++ grub_uint64_t start_time; ++ struct grub_net_dhcp6_option_duid_ll duid; ++ struct grub_net_network_level_interface *iface; ++ ++ /* The associated dhcpv6 options */ ++ grub_dhcp6_options_t adv; ++ grub_dhcp6_options_t reply; ++}; ++ ++typedef struct grub_dhcp6_session *grub_dhcp6_session_t; ++ ++typedef void (*dhcp6_option_hook_fn) (const struct grub_net_dhcp6_option *opt, void *data); ++ ++static void ++foreach_dhcp6_option (const struct grub_net_dhcp6_option *opt, grub_size_t size, ++ dhcp6_option_hook_fn hook, void *hook_data); ++ ++static void ++parse_dhcp6_iaaddr (const struct grub_net_dhcp6_option *opt, void *data) ++{ ++ grub_dhcp6_options_t dhcp6 = (grub_dhcp6_options_t )data; ++ ++ grub_uint16_t code = grub_be_to_cpu16 (opt->code); ++ grub_uint16_t len = grub_be_to_cpu16 (opt->len); ++ ++ if (code == GRUB_NET_DHCP6_OPTION_IAADDR) ++ { ++ const struct grub_net_dhcp6_option_iaaddr *iaaddr; ++ iaaddr = (const struct grub_net_dhcp6_option_iaaddr *)opt->data; ++ ++ if (len < sizeof (*iaaddr)) ++ { ++ grub_dprintf ("bootp", "DHCPv6: code %u with insufficient length %u\n", code, len); ++ return; ++ } ++ if (!dhcp6->ia_addr) ++ { ++ dhcp6->ia_addr = grub_malloc (sizeof(*dhcp6->ia_addr)); ++ dhcp6->ia_addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; ++ dhcp6->ia_addr->ipv6[0] = grub_get_unaligned64 (iaaddr->addr); ++ dhcp6->ia_addr->ipv6[1] = grub_get_unaligned64 (iaaddr->addr + 8); ++ dhcp6->preferred_lifetime = grub_be_to_cpu32 (iaaddr->preferred_lifetime); ++ dhcp6->valid_lifetime = grub_be_to_cpu32 (iaaddr->valid_lifetime); ++ } ++ } ++} ++ ++static void ++parse_dhcp6_option (const struct grub_net_dhcp6_option *opt, void *data) ++{ ++ grub_dhcp6_options_t dhcp6 = (grub_dhcp6_options_t)data; ++ grub_uint16_t code = grub_be_to_cpu16 (opt->code); ++ grub_uint16_t len = grub_be_to_cpu16 (opt->len); ++ ++ switch (code) ++ { ++ case GRUB_NET_DHCP6_OPTION_CLIENTID: ++ ++ if (dhcp6->client_duid || !len) ++ { ++ grub_dprintf ("bootp", "Skipped DHCPv6 CLIENTID with length %u\n", len); ++ break; ++ } ++ dhcp6->client_duid = grub_malloc (len); ++ grub_memcpy (dhcp6->client_duid, opt->data, len); ++ dhcp6->client_duid_len = len; ++ break; ++ ++ case GRUB_NET_DHCP6_OPTION_SERVERID: ++ ++ if (dhcp6->server_duid || !len) ++ { ++ grub_dprintf ("bootp", "Skipped DHCPv6 SERVERID with length %u\n", len); ++ break; ++ } ++ dhcp6->server_duid = grub_malloc (len); ++ grub_memcpy (dhcp6->server_duid, opt->data, len); ++ dhcp6->server_duid_len = len; ++ break; ++ ++ case GRUB_NET_DHCP6_OPTION_IA_NA: ++ { ++ const struct grub_net_dhcp6_option_iana *ia_na; ++ grub_uint16_t data_len; ++ ++ if (dhcp6->iaid || len < sizeof (*ia_na)) ++ { ++ grub_dprintf ("bootp", "Skipped DHCPv6 IA_NA with length %u\n", len); ++ break; ++ } ++ ia_na = (const struct grub_net_dhcp6_option_iana *)opt->data; ++ dhcp6->iaid = grub_be_to_cpu32 (ia_na->iaid); ++ dhcp6->t1 = grub_be_to_cpu32 (ia_na->t1); ++ dhcp6->t2 = grub_be_to_cpu32 (ia_na->t2); ++ ++ data_len = len - sizeof (*ia_na); ++ if (data_len) ++ foreach_dhcp6_option ((const struct grub_net_dhcp6_option *)ia_na->data, data_len, parse_dhcp6_iaaddr, dhcp6); ++ } ++ break; ++ ++ case GRUB_NET_DHCP6_OPTION_DNS_SERVERS: ++ { ++ const grub_uint8_t *po; ++ grub_uint16_t ln; ++ grub_net_network_level_address_t *la; ++ ++ if (!len || len & 0xf) ++ { ++ grub_dprintf ("bootp", "Skip invalid length DHCPv6 DNS_SERVERS \n"); ++ break; ++ } ++ dhcp6->num_dns_server = ln = len >> 4; ++ dhcp6->dns_server_addrs = la = grub_zalloc (ln * sizeof (*la)); ++ ++ for (po = opt->data; ln > 0; po += 0x10, la++, ln--) ++ { ++ la->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; ++ la->ipv6[0] = grub_get_unaligned64 (po); ++ la->ipv6[1] = grub_get_unaligned64 (po + 8); ++ la->option = DNS_OPTION_PREFER_IPV6; ++ } ++ } ++ break; ++ ++ case GRUB_NET_DHCP6_OPTION_BOOTFILE_URL: ++ dissect_url ((const char *)opt->data, ++ &dhcp6->boot_file_proto, ++ &dhcp6->boot_file_server_ip, ++ &dhcp6->boot_file_path); ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++static void ++foreach_dhcp6_option (const struct grub_net_dhcp6_option *opt, grub_size_t size, dhcp6_option_hook_fn hook, void *hook_data) ++{ ++ while (size) ++ { ++ grub_uint16_t code, len; ++ ++ if (size < sizeof (*opt)) ++ { ++ grub_dprintf ("bootp", "DHCPv6: Options stopped with remaining size %" PRIxGRUB_SIZE "\n", size); ++ break; ++ } ++ size -= sizeof (*opt); ++ len = grub_be_to_cpu16 (opt->len); ++ code = grub_be_to_cpu16 (opt->code); ++ if (size < len) ++ { ++ grub_dprintf ("bootp", "DHCPv6: Options stopped at out of bound length %u for option %u\n", len, code); ++ break; ++ } ++ if (!len) ++ { ++ grub_dprintf ("bootp", "DHCPv6: Options stopped at zero length option %u\n", code); ++ break; ++ } ++ else ++ { ++ if (hook) ++ hook (opt, hook_data); ++ size -= len; ++ opt = (const struct grub_net_dhcp6_option *)((grub_uint8_t *)opt + len + sizeof (*opt)); ++ } ++ } ++} ++ ++static grub_dhcp6_options_t ++grub_dhcp6_options_get (const struct grub_net_dhcp6_packet *v6h, ++ grub_size_t size) ++{ ++ grub_dhcp6_options_t options; ++ ++ if (size < sizeof (*v6h)) ++ { ++ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("DHCPv6 packet size too small")); ++ return NULL; ++ } ++ ++ options = grub_zalloc (sizeof(*options)); ++ if (!options) + return NULL; + +- *device = 0; +- *path = 0; +- +- grub_dprintf ("net", "mac address is %02x:%02x:%02x:%02x:%02x:%02x\n", +- hwaddr->mac[0], hwaddr->mac[1], hwaddr->mac[2], +- hwaddr->mac[3], hwaddr->mac[4], hwaddr->mac[5]); +- +- if (is_def) +- grub_net_default_server = 0; +- +- if (is_def && !grub_net_default_server && packet) ++ foreach_dhcp6_option ((const struct grub_net_dhcp6_option *)v6h->dhcp_options, ++ size - sizeof (*v6h), parse_dhcp6_option, options); ++ ++ return options; ++} ++ ++static void ++grub_dhcp6_options_free (grub_dhcp6_options_t options) ++{ ++ if (options->client_duid) ++ grub_free (options->client_duid); ++ if (options->server_duid) ++ grub_free (options->server_duid); ++ if (options->ia_addr) ++ grub_free (options->ia_addr); ++ if (options->dns_server_addrs) ++ grub_free (options->dns_server_addrs); ++ if (options->boot_file_proto) ++ grub_free (options->boot_file_proto); ++ if (options->boot_file_server_ip) ++ grub_free (options->boot_file_server_ip); ++ if (options->boot_file_path) ++ grub_free (options->boot_file_path); ++ ++ grub_free (options); ++} ++ ++static grub_dhcp6_session_t grub_dhcp6_sessions; ++#define FOR_DHCP6_SESSIONS_SAFE(var, next) FOR_LIST_ELEMENTS_SAFE (var, next, grub_dhcp6_sessions) ++#define FOR_DHCP6_SESSIONS(var) FOR_LIST_ELEMENTS (var, grub_dhcp6_sessions) ++ ++static void ++grub_net_configure_by_dhcp6_info (const char *name, ++ struct grub_net_card *card, ++ grub_dhcp6_options_t dhcp6, ++ int is_def, ++ int flags, ++ struct grub_net_network_level_interface **ret_inf) ++{ ++ grub_net_network_level_netaddress_t netaddr; ++ struct grub_net_network_level_interface *inf; ++ ++ if (dhcp6->ia_addr) + { +- const grub_uint8_t *options = packet->dhcp_options; +- unsigned int option_max = 1024 - OFFSET_OF (dhcp_options, packet); +- unsigned int i; +- +- for (i = 0; i < option_max - sizeof (grub_net_dhcpv6_option_t); ) +- { +- grub_uint16_t num, len; +- grub_net_dhcpv6_option_t *opt = +- (grub_net_dhcpv6_option_t *)(options + i); +- +- num = grub_be_to_cpu16(opt->option_num); +- len = grub_be_to_cpu16(opt->option_len); +- +- grub_dprintf ("net", "got dhcpv6 option %d len %d\n", num, len); +- +- if (len == 0) +- break; +- +- if (len + i > 1024) +- break; +- +- if (num == GRUB_NET_DHCP6_BOOTFILE_URL) +- { +- char *scheme, *userinfo, *host, *file; +- char *tmp; +- int hostlen; +- int port; +- int rc = extract_url_info ((const char *)opt->option_data, +- (grub_size_t)len, +- &scheme, &userinfo, &host, &port, +- &file); +- if (rc < 0) +- continue; +- +- /* right now this only handles tftp. */ +- if (grub_strcmp("tftp", scheme)) +- { +- grub_free (scheme); +- grub_free (userinfo); +- grub_free (host); +- grub_free (file); +- continue; +- } +- grub_free (userinfo); +- +- hostlen = grub_strlen (host); +- if (hostlen > 2 && host[0] == '[' && host[hostlen-1] == ']') +- { +- tmp = host+1; +- host[hostlen-1] = '\0'; +- } +- else +- tmp = host; ++ inf = grub_net_add_addr (name, card, dhcp6->ia_addr, &card->default_address, flags); + +- *device = grub_xasprintf ("%s,%s", scheme, tmp); +- grub_free (scheme); +- grub_free (host); ++ netaddr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; ++ netaddr.ipv6.base[0] = dhcp6->ia_addr->ipv6[0]; ++ netaddr.ipv6.base[1] = 0; ++ netaddr.ipv6.masksize = 64; ++ grub_net_add_route (name, netaddr, inf); + +- if (file && *file) +- { +- tmp = grub_strrchr (file, '/'); +- if (tmp) +- *(tmp+1) = '\0'; +- else +- file[0] = '\0'; +- } +- else if (!file) +- file = grub_strdup (""); +- +- if (file[0] == '/') +- { +- *path = grub_strdup (file+1); +- grub_free (file); +- } +- else +- *path = file; +- } +- else if (num == GRUB_NET_DHCP6_IA_NA) +- { +- const grub_net_dhcpv6_option_t *ia_na_opt; +- const grub_net_dhcpv6_opt_ia_na_t *ia_na = +- (const grub_net_dhcpv6_opt_ia_na_t *)opt; +- unsigned int left = len - OFFSET_OF (options, ia_na); +- unsigned int j; +- +- if ((grub_uint8_t *)ia_na + left > +- (grub_uint8_t *)options + option_max) +- left -= ((grub_uint8_t *)ia_na + left) +- - ((grub_uint8_t *)options + option_max); +- +- if (len < OFFSET_OF (option_data, opt) +- + sizeof (grub_net_dhcpv6_option_t)) +- { +- grub_dprintf ("net", +- "found dhcpv6 ia_na option with no address\n"); +- continue; +- } +- +- for (j = 0; left > sizeof (grub_net_dhcpv6_option_t); ) +- { +- ia_na_opt = (const grub_net_dhcpv6_option_t *) +- (ia_na->options + j); +- grub_uint16_t ia_na_opt_num, ia_na_opt_len; +- +- ia_na_opt_num = grub_be_to_cpu16 (ia_na_opt->option_num); +- ia_na_opt_len = grub_be_to_cpu16 (ia_na_opt->option_len); +- if (ia_na_opt_len == 0) +- break; +- if (j + ia_na_opt_len > left) +- break; +- if (ia_na_opt_num == GRUB_NET_DHCP6_IA_ADDRESS) +- { +- const grub_net_dhcpv6_opt_ia_address_t *ia_addr; +- +- ia_addr = (const grub_net_dhcpv6_opt_ia_address_t *) +- ia_na_opt; +- addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; +- grub_memcpy(addr.ipv6, ia_addr->ipv6_address, +- sizeof (ia_addr->ipv6_address)); +- inter = grub_net_add_addr (name, card, &addr, hwaddr, 0); +- } +- +- j += ia_na_opt_len; +- left -= ia_na_opt_len; +- } +- } ++ if (ret_inf) ++ *ret_inf = inf; ++ } + +- i += len + 4; +- } ++ if (dhcp6->dns_server_addrs) ++ { ++ grub_uint16_t i; + +- grub_print_error (); ++ for (i = 0; i < dhcp6->num_dns_server; ++i) ++ grub_net_add_dns_server (dhcp6->dns_server_addrs + i); + } + +- if (is_def) ++ if (dhcp6->boot_file_path) ++ grub_env_set_net_property (name, "boot_file", dhcp6->boot_file_path, ++ grub_strlen (dhcp6->boot_file_path)); ++ ++ if (is_def && dhcp6->boot_file_server_ip) + { ++ grub_net_default_server = grub_strdup (dhcp6->boot_file_server_ip); + grub_env_set ("net_default_interface", name); + grub_env_export ("net_default_interface"); + } ++} ++ ++static void ++grub_dhcp6_session_add (struct grub_net_network_level_interface *iface, ++ grub_uint32_t iaid) ++{ ++ grub_dhcp6_session_t se; ++ struct grub_datetime date; ++ grub_err_t err; ++ grub_int32_t t = 0; ++ ++ se = grub_malloc (sizeof (*se)); ++ ++ err = grub_get_datetime (&date); ++ if (err || !grub_datetime2unixtime (&date, &t)) ++ { ++ grub_errno = GRUB_ERR_NONE; ++ t = 0; ++ } ++ ++ se->iface = iface; ++ se->iaid = iaid; ++ se->transaction_id = t; ++ se->start_time = grub_get_time_ms (); ++ se->duid.type = grub_cpu_to_be16_compile_time (3) ; ++ se->duid.hw_type = grub_cpu_to_be16_compile_time (1); ++ grub_memcpy (&se->duid.hwaddr, &iface->hwaddress.mac, sizeof (se->duid.hwaddr)); ++ se->adv = NULL; ++ se->reply = NULL; ++ grub_list_push (GRUB_AS_LIST_P (&grub_dhcp6_sessions), GRUB_AS_LIST (se)); ++} ++ ++static void ++grub_dhcp6_session_remove (grub_dhcp6_session_t se) ++{ ++ grub_list_remove (GRUB_AS_LIST (se)); ++ if (se->adv) ++ grub_dhcp6_options_free (se->adv); ++ if (se->reply) ++ grub_dhcp6_options_free (se->reply); ++ grub_free (se); ++} ++ ++static void ++grub_dhcp6_session_remove_all (void) ++{ ++ grub_dhcp6_session_t se, next; ++ ++ FOR_DHCP6_SESSIONS_SAFE (se, next) ++ { ++ grub_dhcp6_session_remove (se); ++ } ++ grub_dhcp6_sessions = NULL; ++} ++ ++static grub_err_t ++grub_dhcp6_session_configure_network (grub_dhcp6_session_t se) ++{ ++ char *name; + +- if (inter) +- grub_net_add_ipv6_local (inter, mask); +- return inter; ++ name = grub_xasprintf ("%s:dhcp6", se->iface->card->name); ++ if (!name) ++ return grub_errno; ++ ++ grub_net_configure_by_dhcp6_info (name, se->iface->card, se->reply, 1, 0, 0); ++ grub_free (name); ++ ++ return GRUB_ERR_NONE; + } + ++static grub_err_t ++grub_dhcp6_session_send_request (grub_dhcp6_session_t se) ++{ ++ struct grub_net_buff *nb; ++ struct grub_net_dhcp6_option *opt; ++ struct grub_net_dhcp6_packet *v6h; ++ struct grub_net_dhcp6_option_iana *ia_na; ++ struct grub_net_dhcp6_option_iaaddr *iaaddr; ++ struct udphdr *udph; ++ grub_net_network_level_address_t multicast; ++ grub_net_link_level_address_t ll_multicast; ++ grub_uint64_t elapsed; ++ struct grub_net_network_level_interface *inf = se->iface; ++ grub_dhcp6_options_t dhcp6 = se->adv; ++ grub_err_t err = GRUB_ERR_NONE; ++ ++ multicast.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; ++ multicast.ipv6[0] = grub_cpu_to_be64_compile_time (0xff02ULL << 48); ++ multicast.ipv6[1] = grub_cpu_to_be64_compile_time (0x10002ULL); ++ ++ err = grub_net_link_layer_resolve (inf, &multicast, &ll_multicast); ++ if (err) ++ return err; ++ ++ nb = grub_netbuff_alloc (GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE); ++ ++ if (!nb) ++ return grub_errno; ++ ++ err = grub_netbuff_reserve (nb, GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE); ++ if (err) ++ { ++ grub_netbuff_free (nb); ++ return err; ++ } ++ ++ err = grub_netbuff_push (nb, dhcp6->client_duid_len + sizeof (*opt)); ++ if (err) ++ { ++ grub_netbuff_free (nb); ++ return err; ++ } ++ opt = (struct grub_net_dhcp6_option *)nb->data; ++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_CLIENTID); ++ opt->len = grub_cpu_to_be16 (dhcp6->client_duid_len); ++ grub_memcpy (opt->data, dhcp6->client_duid , dhcp6->client_duid_len); ++ ++ err = grub_netbuff_push (nb, dhcp6->server_duid_len + sizeof (*opt)); ++ if (err) ++ { ++ grub_netbuff_free (nb); ++ return err; ++ } ++ opt = (struct grub_net_dhcp6_option *)nb->data; ++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_SERVERID); ++ opt->len = grub_cpu_to_be16 (dhcp6->server_duid_len); ++ grub_memcpy (opt->data, dhcp6->server_duid , dhcp6->server_duid_len); ++ ++ err = grub_netbuff_push (nb, sizeof (*ia_na) + sizeof (*opt)); ++ if (err) ++ { ++ grub_netbuff_free (nb); ++ return err; ++ } ++ ++ if (dhcp6->ia_addr) ++ { ++ err = grub_netbuff_push (nb, sizeof(*iaaddr) + sizeof (*opt)); ++ if (err) ++ { ++ grub_netbuff_free (nb); ++ return err; ++ } ++ } ++ opt = (struct grub_net_dhcp6_option *)nb->data; ++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IA_NA); ++ opt->len = grub_cpu_to_be16 (sizeof (*ia_na)); ++ if (dhcp6->ia_addr) ++ opt->len += grub_cpu_to_be16 (sizeof(*iaaddr) + sizeof (*opt)); ++ ++ ia_na = (struct grub_net_dhcp6_option_iana *)opt->data; ++ ia_na->iaid = grub_cpu_to_be32 (dhcp6->iaid); ++ ++ ia_na->t1 = grub_cpu_to_be32 (dhcp6->t1); ++ ia_na->t2 = grub_cpu_to_be32 (dhcp6->t2); ++ ++ if (dhcp6->ia_addr) ++ { ++ opt = (struct grub_net_dhcp6_option *)ia_na->data; ++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IAADDR); ++ opt->len = grub_cpu_to_be16 (sizeof (*iaaddr)); ++ iaaddr = (struct grub_net_dhcp6_option_iaaddr *)opt->data; ++ grub_set_unaligned64 (iaaddr->addr, dhcp6->ia_addr->ipv6[0]); ++ grub_set_unaligned64 (iaaddr->addr + 8, dhcp6->ia_addr->ipv6[1]); ++ ++ iaaddr->preferred_lifetime = grub_cpu_to_be32 (dhcp6->preferred_lifetime); ++ iaaddr->valid_lifetime = grub_cpu_to_be32 (dhcp6->valid_lifetime); ++ } ++ ++ err = grub_netbuff_push (nb, sizeof (*opt) + 2 * sizeof (grub_uint16_t)); ++ if (err) ++ { ++ grub_netbuff_free (nb); ++ return err; ++ } ++ ++ opt = (struct grub_net_dhcp6_option*) nb->data; ++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_ORO); ++ opt->len = grub_cpu_to_be16_compile_time (2 * sizeof (grub_uint16_t)); ++ grub_set_unaligned16 (opt->data, grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_BOOTFILE_URL)); ++ grub_set_unaligned16 (opt->data + 2, grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_DNS_SERVERS)); ++ ++ err = grub_netbuff_push (nb, sizeof (*opt) + sizeof (grub_uint16_t)); ++ if (err) ++ { ++ grub_netbuff_free (nb); ++ return err; ++ } ++ opt = (struct grub_net_dhcp6_option*) nb->data; ++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_ELAPSED_TIME); ++ opt->len = grub_cpu_to_be16_compile_time (sizeof (grub_uint16_t)); ++ ++ /* the time is expressed in hundredths of a second */ ++ elapsed = grub_divmod64 (grub_get_time_ms () - se->start_time, 10, 0); ++ ++ if (elapsed > 0xffff) ++ elapsed = 0xffff; ++ ++ grub_set_unaligned16 (opt->data, grub_cpu_to_be16 ((grub_uint16_t)elapsed)); ++ ++ err = grub_netbuff_push (nb, sizeof (*v6h)); ++ if (err) ++ { ++ grub_netbuff_free (nb); ++ return err; ++ } ++ ++ v6h = (struct grub_net_dhcp6_packet *) nb->data; ++ v6h->message_type = GRUB_NET_DHCP6_REQUEST; ++ v6h->transaction_id = se->transaction_id; ++ ++ err = grub_netbuff_push (nb, sizeof (*udph)); ++ if (err) ++ { ++ grub_netbuff_free (nb); ++ return err; ++ } ++ ++ udph = (struct udphdr *) nb->data; ++ udph->src = grub_cpu_to_be16_compile_time (DHCP6_CLIENT_PORT); ++ udph->dst = grub_cpu_to_be16_compile_time (DHCP6_SERVER_PORT); ++ udph->chksum = 0; ++ udph->len = grub_cpu_to_be16 (nb->tail - nb->data); ++ ++ udph->chksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_UDP, ++ &inf->address, ++ &multicast); ++ err = grub_net_send_ip_packet (inf, &multicast, &ll_multicast, nb, ++ GRUB_NET_IP_UDP); ++ ++ grub_netbuff_free (nb); ++ ++ return err; ++} ++ ++struct grub_net_network_level_interface * ++grub_net_configure_by_dhcpv6_reply (const char *name, ++ struct grub_net_card *card, ++ grub_net_interface_flags_t flags, ++ const struct grub_net_dhcp6_packet *v6h, ++ grub_size_t size, ++ int is_def, ++ char **device, char **path) ++{ ++ struct grub_net_network_level_interface *inf; ++ grub_dhcp6_options_t dhcp6; ++ ++ dhcp6 = grub_dhcp6_options_get (v6h, size); ++ if (!dhcp6) ++ { ++ grub_print_error (); ++ return NULL; ++ } ++ ++ grub_net_configure_by_dhcp6_info (name, card, dhcp6, is_def, flags, &inf); ++ ++ if (device && dhcp6->boot_file_proto && dhcp6->boot_file_server_ip) ++ { ++ *device = grub_xasprintf ("%s,%s", dhcp6->boot_file_proto, dhcp6->boot_file_server_ip); ++ grub_print_error (); ++ } ++ if (path && dhcp6->boot_file_path) ++ { ++ *path = grub_strdup (dhcp6->boot_file_path); ++ grub_print_error (); ++ if (*path) ++ { ++ char *slash; ++ slash = grub_strrchr (*path, '/'); ++ if (slash) ++ *slash = 0; ++ else ++ **path = 0; ++ } ++ } ++ ++ grub_dhcp6_options_free (dhcp6); ++ return inf; ++} + + void + grub_net_process_dhcp (struct grub_net_buff *nb, +@@ -546,6 +1038,77 @@ grub_net_process_dhcp (struct grub_net_buff *nb, + } + } + ++grub_err_t ++grub_net_process_dhcp6 (struct grub_net_buff *nb, ++ struct grub_net_card *card __attribute__ ((unused))) ++{ ++ const struct grub_net_dhcp6_packet *v6h; ++ grub_dhcp6_session_t se; ++ grub_size_t size; ++ grub_dhcp6_options_t options; ++ ++ v6h = (const struct grub_net_dhcp6_packet *) nb->data; ++ size = nb->tail - nb->data; ++ ++ options = grub_dhcp6_options_get (v6h, size); ++ if (!options) ++ return grub_errno; ++ ++ if (!options->client_duid || !options->server_duid || !options->ia_addr) ++ { ++ grub_dhcp6_options_free (options); ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Bad DHCPv6 Packet"); ++ } ++ ++ FOR_DHCP6_SESSIONS (se) ++ { ++ if (se->transaction_id == v6h->transaction_id && ++ grub_memcmp (options->client_duid, &se->duid, sizeof (se->duid)) == 0 && ++ se->iaid == options->iaid) ++ break; ++ } ++ ++ if (!se) ++ { ++ grub_dprintf ("bootp", "DHCPv6 session not found\n"); ++ grub_dhcp6_options_free (options); ++ return GRUB_ERR_NONE; ++ } ++ ++ if (v6h->message_type == GRUB_NET_DHCP6_ADVERTISE) ++ { ++ if (se->adv) ++ { ++ grub_dprintf ("bootp", "Skipped DHCPv6 Advertised .. \n"); ++ grub_dhcp6_options_free (options); ++ return GRUB_ERR_NONE; ++ } ++ ++ se->adv = options; ++ return grub_dhcp6_session_send_request (se); ++ } ++ else if (v6h->message_type == GRUB_NET_DHCP6_REPLY) ++ { ++ if (!se->adv) ++ { ++ grub_dprintf ("bootp", "Skipped DHCPv6 Reply .. \n"); ++ grub_dhcp6_options_free (options); ++ return GRUB_ERR_NONE; ++ } ++ ++ se->reply = options; ++ grub_dhcp6_session_configure_network (se); ++ grub_dhcp6_session_remove (se); ++ return GRUB_ERR_NONE; ++ } ++ else ++ { ++ grub_dhcp6_options_free (options); ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ + static grub_err_t + grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +@@ -816,7 +1379,174 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), + return err; + } + +-static grub_command_t cmd_getdhcp, cmd_bootp; ++static grub_err_t ++grub_cmd_bootp6 (struct grub_command *cmd __attribute__ ((unused)), ++ int argc, char **args) ++{ ++ struct grub_net_card *card; ++ grub_uint32_t iaid = 0; ++ int interval; ++ grub_err_t err; ++ grub_dhcp6_session_t se; ++ ++ err = GRUB_ERR_NONE; ++ ++ FOR_NET_CARDS (card) ++ { ++ struct grub_net_network_level_interface *iface; ++ ++ if (argc > 0 && grub_strcmp (card->name, args[0]) != 0) ++ continue; ++ ++ iface = grub_net_ipv6_get_link_local (card, &card->default_address); ++ if (!iface) ++ { ++ grub_dhcp6_session_remove_all (); ++ return grub_errno; ++ } ++ ++ grub_dhcp6_session_add (iface, iaid++); ++ } ++ ++ for (interval = 200; interval < 10000; interval *= 2) ++ { ++ int done = 1; ++ ++ FOR_DHCP6_SESSIONS (se) ++ { ++ struct grub_net_buff *nb; ++ struct grub_net_dhcp6_option *opt; ++ struct grub_net_dhcp6_packet *v6h; ++ struct grub_net_dhcp6_option_duid_ll *duid; ++ struct grub_net_dhcp6_option_iana *ia_na; ++ grub_net_network_level_address_t multicast; ++ grub_net_link_level_address_t ll_multicast; ++ struct udphdr *udph; ++ ++ multicast.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; ++ multicast.ipv6[0] = grub_cpu_to_be64_compile_time (0xff02ULL << 48); ++ multicast.ipv6[1] = grub_cpu_to_be64_compile_time (0x10002ULL); ++ ++ err = grub_net_link_layer_resolve (se->iface, ++ &multicast, &ll_multicast); ++ if (err) ++ { ++ grub_dhcp6_session_remove_all (); ++ return err; ++ } ++ ++ nb = grub_netbuff_alloc (GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE); ++ ++ if (!nb) ++ { ++ grub_dhcp6_session_remove_all (); ++ return grub_errno; ++ } ++ ++ err = grub_netbuff_reserve (nb, GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE); ++ if (err) ++ { ++ grub_dhcp6_session_remove_all (); ++ grub_netbuff_free (nb); ++ return err; ++ } ++ ++ err = grub_netbuff_push (nb, sizeof (*opt) + sizeof (grub_uint16_t)); ++ if (err) ++ { ++ grub_dhcp6_session_remove_all (); ++ grub_netbuff_free (nb); ++ return err; ++ } ++ ++ opt = (struct grub_net_dhcp6_option *)nb->data; ++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_ELAPSED_TIME); ++ opt->len = grub_cpu_to_be16_compile_time (sizeof (grub_uint16_t)); ++ grub_set_unaligned16 (opt->data, 0); ++ ++ err = grub_netbuff_push (nb, sizeof (*opt) + sizeof (*duid)); ++ if (err) ++ { ++ grub_dhcp6_session_remove_all (); ++ grub_netbuff_free (nb); ++ return err; ++ } ++ ++ opt = (struct grub_net_dhcp6_option *)nb->data; ++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_CLIENTID); ++ opt->len = grub_cpu_to_be16 (sizeof (*duid)); ++ ++ duid = (struct grub_net_dhcp6_option_duid_ll *) opt->data; ++ grub_memcpy (duid, &se->duid, sizeof (*duid)); ++ ++ err = grub_netbuff_push (nb, sizeof (*opt) + sizeof (*ia_na)); ++ if (err) ++ { ++ grub_dhcp6_session_remove_all (); ++ grub_netbuff_free (nb); ++ return err; ++ } ++ ++ opt = (struct grub_net_dhcp6_option *)nb->data; ++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IA_NA); ++ opt->len = grub_cpu_to_be16 (sizeof (*ia_na)); ++ ia_na = (struct grub_net_dhcp6_option_iana *)opt->data; ++ ia_na->iaid = grub_cpu_to_be32 (se->iaid); ++ ia_na->t1 = 0; ++ ia_na->t2 = 0; ++ ++ err = grub_netbuff_push (nb, sizeof (*v6h)); ++ if (err) ++ { ++ grub_dhcp6_session_remove_all (); ++ grub_netbuff_free (nb); ++ return err; ++ } ++ ++ v6h = (struct grub_net_dhcp6_packet *)nb->data; ++ v6h->message_type = GRUB_NET_DHCP6_SOLICIT; ++ v6h->transaction_id = se->transaction_id; ++ ++ grub_netbuff_push (nb, sizeof (*udph)); ++ ++ udph = (struct udphdr *) nb->data; ++ udph->src = grub_cpu_to_be16_compile_time (DHCP6_CLIENT_PORT); ++ udph->dst = grub_cpu_to_be16_compile_time (DHCP6_SERVER_PORT); ++ udph->chksum = 0; ++ udph->len = grub_cpu_to_be16 (nb->tail - nb->data); ++ ++ udph->chksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_UDP, ++ &se->iface->address, &multicast); ++ ++ err = grub_net_send_ip_packet (se->iface, &multicast, ++ &ll_multicast, nb, GRUB_NET_IP_UDP); ++ done = 0; ++ grub_netbuff_free (nb); ++ ++ if (err) ++ { ++ grub_dhcp6_session_remove_all (); ++ return err; ++ } ++ } ++ if (!done) ++ grub_net_poll_cards (interval, 0); ++ } ++ ++ FOR_DHCP6_SESSIONS (se) ++ { ++ grub_error_push (); ++ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, ++ N_("couldn't autoconfigure %s"), ++ se->iface->card->name); ++ } ++ ++ grub_dhcp6_session_remove_all (); ++ ++ return err; ++} ++ ++static grub_command_t cmd_getdhcp, cmd_bootp, cmd_bootp6; + + void + grub_bootp_init (void) +@@ -827,6 +1557,9 @@ grub_bootp_init (void) + cmd_getdhcp = grub_register_command ("net_get_dhcp_option", grub_cmd_dhcpopt, + N_("VAR INTERFACE NUMBER DESCRIPTION"), + N_("retrieve DHCP option and save it into VAR. If VAR is - then print the value.")); ++ cmd_bootp6 = grub_register_command ("net_bootp6", grub_cmd_bootp6, ++ N_("[CARD]"), ++ N_("perform a DHCPv6 autoconfiguration")); + } + + void +@@ -834,4 +1567,5 @@ grub_bootp_fini (void) + { + grub_unregister_command (cmd_getdhcp); + grub_unregister_command (cmd_bootp); ++ grub_unregister_command (cmd_bootp6); + } +diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c +index 311213feec1..daa5b03516b 100644 +--- a/grub-core/net/ip.c ++++ b/grub-core/net/ip.c +@@ -235,6 +235,45 @@ handle_dgram (struct grub_net_buff *nb, + { + struct udphdr *udph; + udph = (struct udphdr *) nb->data; ++ ++ if (proto == GRUB_NET_IP_UDP && udph->dst == grub_cpu_to_be16_compile_time (DHCP6_CLIENT_PORT)) ++ { ++ if (udph->chksum) ++ { ++ grub_uint16_t chk, expected; ++ chk = udph->chksum; ++ udph->chksum = 0; ++ expected = grub_net_ip_transport_checksum (nb, ++ GRUB_NET_IP_UDP, ++ source, ++ dest); ++ if (expected != chk) ++ { ++ grub_dprintf ("net", "Invalid UDP checksum. " ++ "Expected %x, got %x\n", ++ grub_be_to_cpu16 (expected), ++ grub_be_to_cpu16 (chk)); ++ grub_netbuff_free (nb); ++ return GRUB_ERR_NONE; ++ } ++ udph->chksum = chk; ++ } ++ ++ err = grub_netbuff_pull (nb, sizeof (*udph)); ++ if (err) ++ { ++ grub_netbuff_free (nb); ++ return err; ++ } ++ ++ err = grub_net_process_dhcp6 (nb, card); ++ if (err) ++ grub_print_error (); ++ ++ grub_netbuff_free (nb); ++ return GRUB_ERR_NONE; ++ } ++ + if (proto == GRUB_NET_IP_UDP && grub_be_to_cpu16 (udph->dst) == 68) + { + const struct grub_net_bootp_packet *bootp; +diff --git a/include/grub/net.h b/include/grub/net.h +index 20e699bb025..8ecfbb49221 100644 +--- a/include/grub/net.h ++++ b/include/grub/net.h +@@ -423,50 +423,65 @@ struct grub_net_bootp_packet + grub_uint8_t vendor[0]; + } GRUB_PACKED; + +-enum +- { +- GRUB_NET_DHCP6_IA_NA = 3, +- GRUB_NET_DHCP6_IA_ADDRESS = 5, +- GRUB_NET_DHCP6_BOOTFILE_URL = 59, +- }; +- +-struct grub_net_dhcpv6_option ++struct grub_net_dhcp6_packet + { +- grub_uint16_t option_num; +- grub_uint16_t option_len; +- grub_uint8_t option_data[]; ++ grub_uint32_t message_type:8; ++ grub_uint32_t transaction_id:24; ++ grub_uint8_t dhcp_options[0]; + } GRUB_PACKED; +-typedef struct grub_net_dhcpv6_option grub_net_dhcpv6_option_t; + +-struct grub_net_dhcpv6_opt_ia_na +-{ +- grub_uint16_t option_num; +- grub_uint16_t option_len; ++struct grub_net_dhcp6_option { ++ grub_uint16_t code; ++ grub_uint16_t len; ++ grub_uint8_t data[0]; ++} GRUB_PACKED; ++ ++struct grub_net_dhcp6_option_iana { + grub_uint32_t iaid; + grub_uint32_t t1; + grub_uint32_t t2; +- grub_uint8_t options[]; ++ grub_uint8_t data[0]; + } GRUB_PACKED; +-typedef struct grub_net_dhcpv6_opt_ia_na grub_net_dhcpv6_opt_ia_na_t; + +-struct grub_net_dhcpv6_opt_ia_address +-{ +- grub_uint16_t option_num; +- grub_uint16_t option_len; +- grub_uint64_t ipv6_address[2]; ++struct grub_net_dhcp6_option_iaaddr { ++ grub_uint8_t addr[16]; + grub_uint32_t preferred_lifetime; + grub_uint32_t valid_lifetime; +- grub_uint8_t options[]; ++ grub_uint8_t data[0]; + } GRUB_PACKED; +-typedef struct grub_net_dhcpv6_opt_ia_address grub_net_dhcpv6_opt_ia_address_t; + +-struct grub_net_dhcpv6_packet ++struct grub_net_dhcp6_option_duid_ll + { +- grub_uint32_t message_type:8; +- grub_uint32_t transaction_id:24; +- grub_uint8_t dhcp_options[1024]; ++ grub_uint16_t type; ++ grub_uint16_t hw_type; ++ grub_uint8_t hwaddr[6]; + } GRUB_PACKED; +-typedef struct grub_net_dhcpv6_packet grub_net_dhcpv6_packet_t; ++ ++enum ++ { ++ GRUB_NET_DHCP6_SOLICIT = 1, ++ GRUB_NET_DHCP6_ADVERTISE = 2, ++ GRUB_NET_DHCP6_REQUEST = 3, ++ GRUB_NET_DHCP6_REPLY = 7 ++ }; ++ ++enum ++ { ++ DHCP6_CLIENT_PORT = 546, ++ DHCP6_SERVER_PORT = 547 ++ }; ++ ++enum ++ { ++ GRUB_NET_DHCP6_OPTION_CLIENTID = 1, ++ GRUB_NET_DHCP6_OPTION_SERVERID = 2, ++ GRUB_NET_DHCP6_OPTION_IA_NA = 3, ++ GRUB_NET_DHCP6_OPTION_IAADDR = 5, ++ GRUB_NET_DHCP6_OPTION_ORO = 6, ++ GRUB_NET_DHCP6_OPTION_ELAPSED_TIME = 8, ++ GRUB_NET_DHCP6_OPTION_DNS_SERVERS = 23, ++ GRUB_NET_DHCP6_OPTION_BOOTFILE_URL = 59 ++ }; + + #define GRUB_NET_BOOTP_RFC1048_MAGIC_0 0x63 + #define GRUB_NET_BOOTP_RFC1048_MAGIC_1 0x82 +@@ -497,12 +512,12 @@ grub_net_configure_by_dhcp_ack (const char *name, + int is_def, char **device, char **path); + + struct grub_net_network_level_interface * +-grub_net_configure_by_dhcpv6_ack (const char *name, +- struct grub_net_card *card, +- grub_net_interface_flags_t flags, +- const grub_net_link_level_address_t *hwaddr, +- const struct grub_net_dhcpv6_packet *packet, +- int is_def, char **device, char **path); ++grub_net_configure_by_dhcpv6_reply (const char *name, ++ struct grub_net_card *card, ++ grub_net_interface_flags_t flags, ++ const struct grub_net_dhcp6_packet *v6, ++ grub_size_t size, ++ int is_def, char **device, char **path); + + int + grub_ipv6_get_masksize(grub_uint16_t *mask); +@@ -519,6 +534,10 @@ void + grub_net_process_dhcp (struct grub_net_buff *nb, + struct grub_net_card *card); + ++grub_err_t ++grub_net_process_dhcp6 (struct grub_net_buff *nb, ++ struct grub_net_card *card); ++ + int + grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a, + const grub_net_link_level_address_t *b); diff --git a/SOURCES/0254-Put-back-our-code-to-add-a-local-route.patch b/SOURCES/0254-Put-back-our-code-to-add-a-local-route.patch new file mode 100644 index 0000000..3c638ba --- /dev/null +++ b/SOURCES/0254-Put-back-our-code-to-add-a-local-route.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 21 Jun 2018 18:32:26 -0400 +Subject: [PATCH] Put back our code to add a local route. + +This was removed by the previous patch. + +Signed-off-by: Peter Jones +--- + grub-core/net/bootp.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c +index 26b3d83d0bc..dd4660601e2 100644 +--- a/grub-core/net/bootp.c ++++ b/grub-core/net/bootp.c +@@ -972,6 +972,7 @@ grub_net_configure_by_dhcpv6_reply (const char *name, + { + struct grub_net_network_level_interface *inf; + grub_dhcp6_options_t dhcp6; ++ int mask = -1; + + dhcp6 = grub_dhcp6_options_get (v6h, size); + if (!dhcp6) +@@ -1003,6 +1004,10 @@ grub_net_configure_by_dhcpv6_reply (const char *name, + } + + grub_dhcp6_options_free (dhcp6); ++ ++ if (inf) ++ grub_net_add_ipv6_local (inf, mask); ++ + return inf; + } + diff --git a/SOURCES/0255-efinet-UEFI-IPv6-PXE-support.patch b/SOURCES/0255-efinet-UEFI-IPv6-PXE-support.patch new file mode 100644 index 0000000..6f0c915 --- /dev/null +++ b/SOURCES/0255-efinet-UEFI-IPv6-PXE-support.patch @@ -0,0 +1,154 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Wed, 15 Apr 2015 14:48:30 +0800 +Subject: [PATCH] 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 +Signed-off-by: Ken Lin +--- + grub-core/net/drivers/efi/efinet.c | 22 ++++++------ + include/grub/efi/api.h | 71 +++++++++++++++++++++++--------------- + 2 files changed, 54 insertions(+), 39 deletions(-) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index b9ed13fcad1..8bb0db014ac 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -404,9 +404,6 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + pxe_mode = pxe->mode; + if (pxe_mode->using_ipv6) + { +- grub_net_link_level_address_t hwaddr; +- struct grub_net_network_level_interface *intf; +- + grub_dprintf ("efinet", "using ipv6 and dhcpv6\n"); + grub_dprintf ("efinet", "dhcp_ack_received: %s%s\n", + pxe_mode->dhcp_ack_received ? "yes" : "no", +@@ -414,16 +411,17 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + if (!pxe_mode->dhcp_ack_received) + continue; + +- hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; +- grub_memcpy (hwaddr.mac, +- card->efi_net->mode->current_address, +- sizeof (hwaddr.mac)); +- +- intf = grub_net_configure_by_dhcpv6_ack (card->name, card, 0, &hwaddr, +- (const struct grub_net_dhcpv6_packet *)&pxe_mode->dhcp_ack.dhcpv6, +- 1, device, path); +- if (intf && device && path) ++ 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 (); ++ if (device && path) + grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path); ++ if (grub_errno) ++ grub_print_error (); + } + else + { +diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h +index 9422ba9a9db..2d0f37a8164 100644 +--- a/include/grub/efi/api.h ++++ b/include/grub/efi/api.h +@@ -1446,31 +1446,6 @@ typedef union + grub_efi_pxe_dhcpv6_packet_t dhcpv6; + } grub_efi_pxe_packet_t; + +-#define GRUB_EFI_PXE_MAX_IPCNT 8 +-#define GRUB_EFI_PXE_MAX_ARP_ENTRIES 8 +-#define GRUB_EFI_PXE_MAX_ROUTE_ENTRIES 8 +- +-typedef struct grub_efi_pxe_ip_filter +-{ +- grub_efi_uint8_t filters; +- grub_efi_uint8_t ip_count; +- grub_efi_uint8_t reserved; +- grub_efi_ip_address_t ip_list[GRUB_EFI_PXE_MAX_IPCNT]; +-} grub_efi_pxe_ip_filter_t; +- +-typedef struct grub_efi_pxe_arp_entry +-{ +- grub_efi_ip_address_t ip_addr; +- grub_efi_mac_address_t mac_addr; +-} grub_efi_pxe_arp_entry_t; +- +-typedef struct grub_efi_pxe_route_entry +-{ +- grub_efi_ip_address_t ip_addr; +- grub_efi_ip_address_t subnet_mask; +- grub_efi_ip_address_t gateway_addr; +-} grub_efi_pxe_route_entry_t; +- + typedef struct grub_efi_pxe_icmp_error + { + grub_efi_uint8_t type; +@@ -1496,6 +1471,48 @@ typedef struct grub_efi_pxe_tftp_error + grub_efi_char8_t error_string[127]; + } grub_efi_pxe_tftp_error_t; + ++typedef struct { ++ grub_uint8_t addr[4]; ++} grub_efi_pxe_ipv4_address_t; ++ ++typedef struct { ++ grub_uint8_t addr[16]; ++} grub_efi_pxe_ipv6_address_t; ++ ++typedef struct { ++ grub_uint8_t addr[32]; ++} grub_efi_pxe_mac_address_t; ++ ++typedef union { ++ grub_uint32_t addr[4]; ++ grub_efi_pxe_ipv4_address_t v4; ++ grub_efi_pxe_ipv6_address_t v6; ++} grub_efi_pxe_ip_address_t; ++ ++#define GRUB_EFI_PXE_BASE_CODE_MAX_IPCNT 8 ++typedef struct grub_efi_pxe_ip_filter ++{ ++ grub_efi_uint8_t filters; ++ grub_efi_uint8_t ip_count; ++ grub_efi_uint16_t reserved; ++ grub_efi_ip_address_t ip_list[GRUB_EFI_PXE_BASE_CODE_MAX_IPCNT]; ++} grub_efi_pxe_ip_filter_t; ++ ++typedef struct { ++ grub_efi_pxe_ip_address_t ip_addr; ++ grub_efi_pxe_mac_address_t mac_addr; ++} grub_efi_pxe_arp_entry_t; ++ ++typedef struct { ++ grub_efi_pxe_ip_address_t ip_addr; ++ grub_efi_pxe_ip_address_t subnet_mask; ++ grub_efi_pxe_ip_address_t gw_addr; ++} grub_efi_pxe_route_entry_t; ++ ++ ++#define GRUB_EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES 8 ++#define GRUB_EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES 8 ++ + typedef struct grub_efi_pxe_mode + { + grub_efi_boolean_t started; +@@ -1527,9 +1544,9 @@ typedef struct grub_efi_pxe_mode + grub_efi_pxe_packet_t pxe_bis_reply; + grub_efi_pxe_ip_filter_t ip_filter; + grub_efi_uint32_t arp_cache_entries; +- grub_efi_pxe_arp_entry_t arp_cache[GRUB_EFI_PXE_MAX_ARP_ENTRIES]; ++ grub_efi_pxe_arp_entry_t arp_cache[GRUB_EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES]; + grub_efi_uint32_t route_table_entries; +- grub_efi_pxe_route_entry_t route_table[GRUB_EFI_PXE_MAX_ROUTE_ENTRIES]; ++ grub_efi_pxe_route_entry_t route_table[GRUB_EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES]; + grub_efi_pxe_icmp_error_t icmp_error; + grub_efi_pxe_tftp_error_t tftp_error; + } grub_efi_pxe_mode_t; diff --git a/SOURCES/0256-grub.texi-Add-net_bootp6-doument.patch b/SOURCES/0256-grub.texi-Add-net_bootp6-doument.patch new file mode 100644 index 0000000..da2c8e7 --- /dev/null +++ b/SOURCES/0256-grub.texi-Add-net_bootp6-doument.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Tue, 5 May 2015 14:19:24 +0800 +Subject: [PATCH] grub.texi: Add net_bootp6 doument + +Update grub documentation for net_bootp6 command. + +Signed-off-by: Michael Chang +Signed-off-by: Ken Lin +--- + docs/grub.texi | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/docs/grub.texi b/docs/grub.texi +index 98138e04d5b..bd3457af9a9 100644 +--- a/docs/grub.texi ++++ b/docs/grub.texi +@@ -5159,6 +5159,7 @@ List available video modes. If resolution is given, show only matching modes. + * 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 +@@ -5240,6 +5241,22 @@ Sets environment variable @samp{net_}@var{}@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 diff --git a/SOURCES/0257-bootp-Add-processing-DHCPACK-packet-from-HTTP-Boot.patch b/SOURCES/0257-bootp-Add-processing-DHCPACK-packet-from-HTTP-Boot.patch new file mode 100644 index 0000000..0e8ea37 --- /dev/null +++ b/SOURCES/0257-bootp-Add-processing-DHCPACK-packet-from-HTTP-Boot.patch @@ -0,0 +1,135 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Thu, 14 Jul 2016 18:45:14 +0800 +Subject: [PATCH] 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 +Signed-off-by: Ken Lin +--- + grub-core/net/bootp.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++-- + include/grub/net.h | 1 + + 2 files changed, 67 insertions(+), 2 deletions(-) + +diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c +index dd4660601e2..d47ad80a2ad 100644 +--- a/grub-core/net/bootp.c ++++ b/grub-core/net/bootp.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -254,6 +255,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); +@@ -356,6 +362,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)); +@@ -417,8 +483,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 8ecfbb49221..1ec827b9bf3 100644 +--- a/include/grub/net.h ++++ b/include/grub/net.h +@@ -498,6 +498,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_CLIENT_ID = 0x3d, + GRUB_NET_BOOTP_CLIENT_UUID = 0x61, + GRUB_NET_BOOTP_END = 0xff diff --git a/SOURCES/0258-efinet-Setting-network-from-UEFI-device-path.patch b/SOURCES/0258-efinet-Setting-network-from-UEFI-device-path.patch new file mode 100644 index 0000000..97af921 --- /dev/null +++ b/SOURCES/0258-efinet-Setting-network-from-UEFI-device-path.patch @@ -0,0 +1,396 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Sun, 10 Jul 2016 23:46:31 +0800 +Subject: [PATCH] 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 +Signed-off-by: Ken Lin +--- + grub-core/net/drivers/efi/efinet.c | 273 +++++++++++++++++++++++++++++++++++-- + include/grub/efi/api.h | 11 ++ + 2 files changed, 275 insertions(+), 9 deletions(-) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index 8bb0db014ac..6f75ff1f9d1 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -342,6 +343,227 @@ grub_efinet_findcards (void) + grub_free (handles); + } + ++static struct grub_net_buff * ++grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *use_ipv6) ++{ ++ grub_efi_uint16_t uri_len; ++ grub_efi_device_path_t *ldp, *ddp; ++ grub_efi_uri_device_path_t *uri_dp; ++ struct grub_net_buff *nb; ++ grub_err_t err; ++ ++ ddp = grub_efi_duplicate_device_path (dp); ++ if (!ddp) ++ return NULL; ++ ++ ldp = grub_efi_find_last_device_path (ddp); ++ ++ if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE ++ || GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_URI_DEVICE_PATH_SUBTYPE) ++ { ++ grub_free (ddp); ++ return NULL; ++ } ++ ++ uri_len = GRUB_EFI_DEVICE_PATH_LENGTH (ldp) > 4 ? GRUB_EFI_DEVICE_PATH_LENGTH (ldp) - 4 : 0; ++ ++ if (!uri_len) ++ { ++ grub_free (ddp); ++ return NULL; ++ } ++ ++ uri_dp = (grub_efi_uri_device_path_t *) ldp; ++ ++ ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; ++ ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; ++ ldp->length = sizeof (*ldp); ++ ++ ldp = grub_efi_find_last_device_path (ddp); ++ ++ if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE ++ || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE ++ && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE)) ++ { ++ grub_free (ddp); ++ return NULL; ++ } ++ ++ nb = grub_netbuff_alloc (512); ++ if (!nb) ++ { ++ grub_free (ddp); ++ return NULL; ++ } ++ ++ if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE) ++ { ++ grub_efi_ipv4_device_path_t *ipv4 = (grub_efi_ipv4_device_path_t *) ldp; ++ struct grub_net_bootp_packet *bp; ++ grub_uint8_t *ptr; ++ ++ bp = (struct grub_net_bootp_packet *) nb->tail; ++ err = grub_netbuff_put (nb, sizeof (*bp) + 4); ++ if (err) ++ { ++ grub_free (ddp); ++ grub_netbuff_free (nb); ++ return NULL; ++ } ++ ++ if (sizeof(bp->boot_file) < uri_len) ++ { ++ grub_free (ddp); ++ grub_netbuff_free (nb); ++ return NULL; ++ } ++ grub_memcpy (bp->boot_file, uri_dp->uri, uri_len); ++ grub_memcpy (&bp->your_ip, ipv4->local_ip_address, sizeof (bp->your_ip)); ++ grub_memcpy (&bp->server_ip, ipv4->remote_ip_address, sizeof (bp->server_ip)); ++ ++ bp->vendor[0] = GRUB_NET_BOOTP_RFC1048_MAGIC_0; ++ bp->vendor[1] = GRUB_NET_BOOTP_RFC1048_MAGIC_1; ++ bp->vendor[2] = GRUB_NET_BOOTP_RFC1048_MAGIC_2; ++ bp->vendor[3] = GRUB_NET_BOOTP_RFC1048_MAGIC_3; ++ ++ ptr = nb->tail; ++ err = grub_netbuff_put (nb, sizeof (ipv4->subnet_mask) + 2); ++ if (err) ++ { ++ grub_free (ddp); ++ grub_netbuff_free (nb); ++ return NULL; ++ } ++ *ptr++ = GRUB_NET_BOOTP_NETMASK; ++ *ptr++ = sizeof (ipv4->subnet_mask); ++ grub_memcpy (ptr, ipv4->subnet_mask, sizeof (ipv4->subnet_mask)); ++ ++ ptr = nb->tail; ++ err = grub_netbuff_put (nb, sizeof (ipv4->gateway_ip_address) + 2); ++ if (err) ++ { ++ grub_free (ddp); ++ grub_netbuff_free (nb); ++ return NULL; ++ } ++ *ptr++ = GRUB_NET_BOOTP_ROUTER; ++ *ptr++ = sizeof (ipv4->gateway_ip_address); ++ grub_memcpy (ptr, ipv4->gateway_ip_address, sizeof (ipv4->gateway_ip_address)); ++ ++ ptr = nb->tail; ++ err = grub_netbuff_put (nb, sizeof ("HTTPClient") + 1); ++ if (err) ++ { ++ grub_free (ddp); ++ grub_netbuff_free (nb); ++ return NULL; ++ } ++ *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) +@@ -358,6 +580,10 @@ 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; +@@ -381,11 +607,21 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + */ + 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; +@@ -398,11 +634,26 @@ 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; ++ 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; ++ } + +- pxe_mode = pxe->mode; +- if (pxe_mode->using_ipv6) ++ if (ipv6) + { + grub_dprintf ("efinet", "using ipv6 and dhcpv6\n"); + grub_dprintf ("efinet", "dhcp_ack_received: %s%s\n", +@@ -413,8 +664,8 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + + 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 (); +@@ -428,11 +679,15 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + grub_dprintf ("efinet", "using ipv4 and dhcp\n"); + 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); + grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path); + } ++ ++ if (nb) ++ grub_netbuff_free (nb); ++ + return; + } + } +diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h +index 2d0f37a8164..76ad56aa2b0 100644 +--- a/include/grub/efi/api.h ++++ b/include/grub/efi/api.h +@@ -786,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; + +@@ -840,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. */ diff --git a/SOURCES/0259-efinet-Setting-DNS-server-from-UEFI-protocol.patch b/SOURCES/0259-efinet-Setting-DNS-server-from-UEFI-protocol.patch new file mode 100644 index 0000000..3623e0c --- /dev/null +++ b/SOURCES/0259-efinet-Setting-DNS-server-from-UEFI-protocol.patch @@ -0,0 +1,337 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Thu, 14 Jul 2016 17:48:45 +0800 +Subject: [PATCH] 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 +Signed-off-by: Ken Lin +--- + 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 6f75ff1f9d1..25616a9c6c8 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -34,6 +34,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, +@@ -343,6 +345,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) + { +@@ -401,6 +522,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); +@@ -462,6 +585,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) +@@ -494,6 +636,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)); +@@ -557,6 +701,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 76ad56aa2b0..852daddfb0f 100644 +--- a/include/grub/efi/api.h ++++ b/include/grub/efi/api.h +@@ -289,6 +289,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; +@@ -1785,6 +1795,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__) + diff --git a/SOURCES/0260-set-rootpath.patch b/SOURCES/0260-set-rootpath.patch new file mode 100644 index 0000000..155cc30 --- /dev/null +++ b/SOURCES/0260-set-rootpath.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 24 May 2017 15:02:40 -0400 +Subject: [PATCH] set rootpath + +Signed-off-by: Peter Jones +--- + grub-core/net/bootp.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c +index d47ad80a2ad..249ca0c2dc6 100644 +--- a/grub-core/net/bootp.c ++++ b/grub-core/net/bootp.c +@@ -398,11 +398,31 @@ grub_net_configure_by_dhcp_ack (const char *name, + if (*path) + { + char *slash; ++ int root_path_len; + slash = grub_strrchr (*path, '/'); + if (slash) + *slash = 0; + else + **path = 0; ++ root_path_len = grub_strlen (*path); ++ if (root_path_len >= 9 && ++ !grub_strcasecmp (&(*path)[root_path_len - 9], "/efi/boot")) ++ { ++ char *root_path; ++ grub_print_error (); ++ if (root_path_len - 9 == 0) ++ { ++ root_path_len = 1; ++ root_path = grub_xasprintf ("/"); ++ } ++ else ++ { ++ root_path_len -= 9; ++ root_path = grub_strndup (*path, root_path_len); ++ } ++ grub_env_set_net_property (name, "rootpath", ++ root_path, root_path_len); ++ } + } + } + grub_net_add_ipv4_local (inter, mask); diff --git a/SOURCES/0261-Fix-one-more-coverity-complaint.patch b/SOURCES/0261-Fix-one-more-coverity-complaint.patch new file mode 100644 index 0000000..ba00fbd --- /dev/null +++ b/SOURCES/0261-Fix-one-more-coverity-complaint.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 25 May 2017 11:27:40 -0400 +Subject: [PATCH] Fix one more coverity complaint + +No idea why covscan thinks this is an "added" bug, since the file hasn't +changed in 3 years, but... yeah. + +Signed-off-by: Peter Jones +--- + grub-core/normal/completion.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/grub-core/normal/completion.c b/grub-core/normal/completion.c +index 2c9b9e9312a..93aa0d8eda8 100644 +--- a/grub-core/normal/completion.c ++++ b/grub-core/normal/completion.c +@@ -284,7 +284,8 @@ complete_file (void) + + /* Cut away the filename part. */ + dirfile = grub_strrchr (dir, '/'); +- dirfile[1] = '\0'; ++ if (dirfile) ++ dirfile[1] = '\0'; + + /* Iterate the directory. */ + (fs->dir) (dev, dir, iterate_dir, NULL); diff --git a/SOURCES/0262-Fix-up-linux-params-usage.patch b/SOURCES/0262-Fix-up-linux-params-usage.patch new file mode 100644 index 0000000..0024568 --- /dev/null +++ b/SOURCES/0262-Fix-up-linux-params-usage.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 30 May 2017 14:16:07 -0400 +Subject: [PATCH] Fix up linux params usage... + +Related: rhbz#1310763 + +Signed-off-by: Peter Jones +--- + grub-core/loader/i386/linux.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c +index e3906eb658f..656c75fd7e8 100644 +--- a/grub-core/loader/i386/linux.c ++++ b/grub-core/loader/i386/linux.c +@@ -680,6 +680,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + { + grub_file_t file = 0; + struct linux_kernel_header lh; ++ grub_uint8_t *linux_params_ptr; + grub_uint8_t setup_sects; + grub_size_t real_size, prot_size, prot_file_size, kernel_offset; + grub_ssize_t len; +@@ -811,6 +812,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + preferred_address)) + goto fail; + ++ + grub_memset (&linux_params, 0, sizeof (linux_params)); + grub_memcpy (&linux_params.setup_sects, &lh.setup_sects, sizeof (lh) - 0x1F1); + +@@ -820,7 +822,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + + len = sizeof (linux_params) - sizeof (lh); + +- grub_memcpy (&linux_params + sizeof (lh), kernel + kernel_offset, len); ++ linux_params_ptr = (void *)&linux_params; ++ grub_memcpy (linux_params_ptr + sizeof (lh), kernel + kernel_offset, len); + kernel_offset += len; + + linux_params.type_of_loader = GRUB_LINUX_BOOT_LOADER_TYPE; diff --git a/SOURCES/0263-Fix-grub_net_hwaddr_to_str.patch b/SOURCES/0263-Fix-grub_net_hwaddr_to_str.patch new file mode 100644 index 0000000..c6f2d4f --- /dev/null +++ b/SOURCES/0263-Fix-grub_net_hwaddr_to_str.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Salter +Date: Tue, 22 Aug 2017 12:21:12 -0400 +Subject: [PATCH] Fix grub_net_hwaddr_to_str + +commit 5c3b78c92f8 introduced support for larger network hw addresses. +However, grub_net_hwaddr_to_str() relies on GRUB_NET_MAX_STR_ADDRESS_SIZE +to prevent a spurious ':' at the end of the string. So now, if actual +hwaddr size is less than max, an extra ':' appears at the end of the +string. So calculate max string size based on actual hwaddr length to +fix the problem. + +Signed-off-by: Mark Salter +--- + grub-core/net/net.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/grub-core/net/net.c b/grub-core/net/net.c +index 6b4b10ba444..a6566bdb00a 100644 +--- a/grub-core/net/net.c ++++ b/grub-core/net/net.c +@@ -784,6 +784,7 @@ grub_net_hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str) + { + char *ptr; + unsigned i; ++ int maxstr; + + if (addr->len > GRUB_NET_MAX_LINK_ADDRESS_SIZE) + { +@@ -792,9 +793,10 @@ grub_net_hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str) + addr->type, addr->len); + return; + } ++ maxstr = addr->len * grub_strlen ("XX:"); + for (ptr = str, i = 0; i < addr->len; i++) + { +- ptr += grub_snprintf (ptr, GRUB_NET_MAX_STR_HWADDR_LEN - (ptr - str), ++ ptr += grub_snprintf (ptr, maxstr - (ptr - str), + "%02x:", addr->mac[i] & 0xff); + } + } diff --git a/SOURCES/0264-Fixup-for-newer-compiler.patch b/SOURCES/0264-Fixup-for-newer-compiler.patch new file mode 100644 index 0000000..e3a56de --- /dev/null +++ b/SOURCES/0264-Fixup-for-newer-compiler.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 10 May 2018 13:40:19 -0400 +Subject: [PATCH] Fixup for newer compiler + +--- + grub-core/fs/btrfs.c | 2 +- + include/grub/gpt_partition.h | 2 +- + conf/Makefile.common | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c +index f7b6c152037..4a6efffeb46 100644 +--- a/grub-core/fs/btrfs.c ++++ b/grub-core/fs/btrfs.c +@@ -183,7 +183,7 @@ struct grub_btrfs_inode + grub_uint64_t size; + grub_uint8_t dummy2[0x70]; + struct grub_btrfs_time mtime; +-} GRUB_PACKED; ++} GRUB_PACKED __attribute__ ((aligned(8))); + + struct grub_btrfs_extent_data + { +diff --git a/include/grub/gpt_partition.h b/include/grub/gpt_partition.h +index 1b32f6725a4..8cddf997efc 100644 +--- a/include/grub/gpt_partition.h ++++ b/include/grub/gpt_partition.h +@@ -76,7 +76,7 @@ struct grub_gpt_partentry + grub_uint64_t end; + grub_uint64_t attrib; + char name[72]; +-} GRUB_PACKED; ++} GRUB_PACKED __attribute__ ((aligned(8))); + + grub_err_t + grub_gpt_partition_map_iterate (grub_disk_t disk, +diff --git a/conf/Makefile.common b/conf/Makefile.common +index 6f836d82771..9e0e8364f38 100644 +--- a/conf/Makefile.common ++++ b/conf/Makefile.common +@@ -45,7 +45,7 @@ CFLAGS_KERNEL = $(CFLAGS_CPU) $(CFLAGS_PLATFORM) -ffreestanding + LDFLAGS_KERNEL = $(LDFLAGS_CPU) $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) $(TARGET_LDFLAGS_STATIC_LIBGCC) + CPPFLAGS_KERNEL = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) -DGRUB_KERNEL=1 + CCASFLAGS_KERNEL = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) +-STRIPFLAGS_KERNEL = -R .eh_frame -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version ++STRIPFLAGS_KERNEL = -R .eh_frame -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version -R .MIPS.abiflags -R .ARM.exidx -R .note.gnu.property -R .gnu.build.attributes + + CFLAGS_MODULE = $(CFLAGS_CPU) $(CFLAGS_PLATFORM) -ffreestanding + LDFLAGS_MODULE = $(LDFLAGS_CPU) $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-r,-d diff --git a/SOURCES/0265-Support-UEFI-networking-protocols.patch b/SOURCES/0265-Support-UEFI-networking-protocols.patch new file mode 100644 index 0000000..bda2ee2 --- /dev/null +++ b/SOURCES/0265-Support-UEFI-networking-protocols.patch @@ -0,0 +1,5055 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Wed, 22 Feb 2017 14:27:50 +0800 +Subject: [PATCH] Support UEFI networking protocols + +References: fate#320130, bsc#1015589, bsc#1076132 +Patch-Mainline: no + +V1: + * Add preliminary support of UEFI networking protocols + * Support UEFI HTTPS Boot + +V2: + * Workaround http data access in firmware + * Fix DNS device path parsing for efinet device + * Relaxed UEFI Protocol requirement + * Support Intel OPA (Omni-Path Architecture) PXE Boot + +V3: + * Fix bufio in calculating address of next_buf + * Check HTTP respond code + * Use HEAD request method to test before GET + * Finish HTTP transaction in one go + * Fix bsc#1076132 +--- + grub-core/Makefile.core.def | 18 + + grub-core/io/bufio.c | 2 +- + grub-core/kern/efi/efi.c | 96 ++- + grub-core/net/drivers/efi/efinet.c | 27 + + grub-core/net/efi/dhcp.c | 397 ++++++++++ + grub-core/net/efi/efi_netfs.c | 57 ++ + grub-core/net/efi/http.c | 419 +++++++++++ + grub-core/net/efi/ip4_config.c | 398 ++++++++++ + grub-core/net/efi/ip6_config.c | 422 +++++++++++ + grub-core/net/efi/net.c | 1428 ++++++++++++++++++++++++++++++++++++ + grub-core/net/efi/pxe.c | 424 +++++++++++ + grub-core/net/net.c | 74 ++ + util/grub-mknetdir.c | 23 +- + include/grub/efi/api.h | 180 ++++- + include/grub/efi/dhcp.h | 343 +++++++++ + include/grub/efi/http.h | 215 ++++++ + include/grub/net/efi.h | 144 ++++ + 17 files changed, 4626 insertions(+), 41 deletions(-) + create mode 100644 grub-core/net/efi/dhcp.c + create mode 100644 grub-core/net/efi/efi_netfs.c + create mode 100644 grub-core/net/efi/http.c + create mode 100644 grub-core/net/efi/ip4_config.c + create mode 100644 grub-core/net/efi/ip6_config.c + create mode 100644 grub-core/net/efi/net.c + create mode 100644 grub-core/net/efi/pxe.c + create mode 100644 include/grub/efi/dhcp.h + create mode 100644 include/grub/efi/http.h + create mode 100644 include/grub/net/efi.h + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index b340ceeec7f..00110ae5efd 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -2093,6 +2093,18 @@ module = { + common = hook/datehook.c; + }; + ++module = { ++ name = efi_netfs; ++ common = net/efi/efi_netfs.c; ++ common = net/efi/net.c; ++ common = net/efi/http.c; ++ common = net/efi/pxe.c; ++ common = net/efi/ip4_config.c; ++ common = net/efi/ip6_config.c; ++ common = net/efi/dhcp.c; ++ enable = efi; ++}; ++ + module = { + name = net; + common = net/net.c; +@@ -2107,6 +2119,12 @@ module = { + common = net/arp.c; + common = net/netbuff.c; + common = net/url.c; ++ efi = net/efi/net.c; ++ efi = net/efi/http.c; ++ efi = net/efi/pxe.c; ++ efi = net/efi/ip4_config.c; ++ efi = net/efi/ip6_config.c; ++ efi = net/efi/dhcp.c; + }; + + module = { +diff --git a/grub-core/io/bufio.c b/grub-core/io/bufio.c +index 22438277d74..d0b0f71b6ed 100644 +--- a/grub-core/io/bufio.c ++++ b/grub-core/io/bufio.c +@@ -132,7 +132,7 @@ grub_bufio_read (grub_file_t file, char *buf, grub_size_t len) + return res; + + /* Need to read some more. */ +- next_buf = (file->offset + res + len - 1) & ~((grub_off_t) bufio->block_size - 1); ++ next_buf = (grub_divmod64 (file->offset + res + len - 1, bufio->block_size, NULL)) * bufio->block_size; + /* Now read between file->offset + res and bufio->buffer_at. */ + if (file->offset + res < next_buf) + { +diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c +index 101307fc71e..570535f78d0 100644 +--- a/grub-core/kern/efi/efi.c ++++ b/grub-core/kern/efi/efi.c +@@ -674,7 +674,7 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp) + { + grub_efi_ipv4_device_path_t *ipv4 + = (grub_efi_ipv4_device_path_t *) dp; +- grub_printf ("/IPv4(%u.%u.%u.%u,%u.%u.%u.%u,%u,%u,%x,%x)", ++ grub_printf ("/IPv4(%u.%u.%u.%u,%u.%u.%u.%u,%u,%u,%x,%x", + (unsigned) ipv4->local_ip_address[0], + (unsigned) ipv4->local_ip_address[1], + (unsigned) ipv4->local_ip_address[2], +@@ -687,33 +687,60 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp) + (unsigned) ipv4->remote_port, + (unsigned) ipv4->protocol, + (unsigned) ipv4->static_ip_address); ++ if (len == sizeof (*ipv4)) ++ { ++ grub_printf (",%u.%u.%u.%u,%u.%u.%u.%u", ++ (unsigned) ipv4->gateway_ip_address[0], ++ (unsigned) ipv4->gateway_ip_address[1], ++ (unsigned) ipv4->gateway_ip_address[2], ++ (unsigned) ipv4->gateway_ip_address[3], ++ (unsigned) ipv4->subnet_mask[0], ++ (unsigned) ipv4->subnet_mask[1], ++ (unsigned) ipv4->subnet_mask[2], ++ (unsigned) ipv4->subnet_mask[3]); ++ } ++ grub_printf (")"); + } + break; + case GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE: + { + grub_efi_ipv6_device_path_t *ipv6 + = (grub_efi_ipv6_device_path_t *) dp; +- grub_printf ("/IPv6(%x:%x:%x:%x:%x:%x:%x:%x,%x:%x:%x:%x:%x:%x:%x:%x,%u,%u,%x,%x)", +- (unsigned) ipv6->local_ip_address[0], +- (unsigned) ipv6->local_ip_address[1], +- (unsigned) ipv6->local_ip_address[2], +- (unsigned) ipv6->local_ip_address[3], +- (unsigned) ipv6->local_ip_address[4], +- (unsigned) ipv6->local_ip_address[5], +- (unsigned) ipv6->local_ip_address[6], +- (unsigned) ipv6->local_ip_address[7], +- (unsigned) ipv6->remote_ip_address[0], +- (unsigned) ipv6->remote_ip_address[1], +- (unsigned) ipv6->remote_ip_address[2], +- (unsigned) ipv6->remote_ip_address[3], +- (unsigned) ipv6->remote_ip_address[4], +- (unsigned) ipv6->remote_ip_address[5], +- (unsigned) ipv6->remote_ip_address[6], +- (unsigned) ipv6->remote_ip_address[7], ++ grub_printf ("/IPv6(%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x,%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x,%u,%u,%x,%x", ++ (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[0]), ++ (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[1]), ++ (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[2]), ++ (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[3]), ++ (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[4]), ++ (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[5]), ++ (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[6]), ++ (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[7]), ++ (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[0]), ++ (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[1]), ++ (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[2]), ++ (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[3]), ++ (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[4]), ++ (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[5]), ++ (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[6]), ++ (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[7]), + (unsigned) ipv6->local_port, + (unsigned) ipv6->remote_port, + (unsigned) ipv6->protocol, + (unsigned) ipv6->static_ip_address); ++ if (len == sizeof (*ipv6)) ++ { ++ grub_printf (",%u,%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", ++ (unsigned) ipv6->prefix_length, ++ (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[0]), ++ (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[1]), ++ (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[2]), ++ (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[3]), ++ (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[4]), ++ (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[5]), ++ (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[6]), ++ (unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[7])); ++ } ++ grub_printf (")"); + } + break; + case GRUB_EFI_INFINIBAND_DEVICE_PATH_SUBTYPE: +@@ -753,6 +780,39 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp) + dump_vendor_path ("Messaging", + (grub_efi_vendor_device_path_t *) dp); + break; ++ case GRUB_EFI_URI_DEVICE_PATH_SUBTYPE: ++ { ++ grub_efi_uri_device_path_t *uri ++ = (grub_efi_uri_device_path_t *) dp; ++ grub_printf ("/URI(%s)", uri->uri); ++ } ++ break; ++ case GRUB_EFI_DNS_DEVICE_PATH_SUBTYPE: ++ { ++ grub_efi_dns_device_path_t *dns ++ = (grub_efi_dns_device_path_t *) dp; ++ if (dns->is_ipv6) ++ { ++ grub_printf ("/DNS(%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x)", ++ (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[0]) >> 16), ++ (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[0])), ++ (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[1]) >> 16), ++ (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[1])), ++ (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[2]) >> 16), ++ (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[2])), ++ (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[3]) >> 16), ++ (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[3]))); ++ } ++ else ++ { ++ grub_printf ("/DNS(%d.%d.%d.%d)", ++ dns->dns_server_ip[0].v4.addr[0], ++ dns->dns_server_ip[0].v4.addr[1], ++ dns->dns_server_ip[0].v4.addr[2], ++ dns->dns_server_ip[0].v4.addr[3]); ++ } ++ } ++ break; + default: + grub_printf ("/UnknownMessaging(%x)", (unsigned) subtype); + break; +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index 25616a9c6c8..3bea6221745 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -502,6 +503,17 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u + + ldp = grub_efi_find_last_device_path (ddp); + ++ /* Skip the DNS Device */ ++ if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE ++ && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_DNS_DEVICE_PATH_SUBTYPE) ++ { ++ 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)) +@@ -771,6 +783,7 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + 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_DNS_DEVICE_PATH_SUBTYPE + && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)) + continue; + dup_dp = grub_efi_duplicate_device_path (dp); +@@ -785,6 +798,15 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + dup_ldp->length = sizeof (*dup_ldp); + } + ++ dup_ldp = grub_efi_find_last_device_path (dup_dp); ++ if (GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_DNS_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; +@@ -857,6 +879,9 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + + GRUB_MOD_INIT(efinet) + { ++ if (grub_efi_net_config) ++ return; ++ + grub_efinet_findcards (); + grub_efi_net_config = grub_efi_net_config_real; + } +@@ -868,5 +893,7 @@ GRUB_MOD_FINI(efinet) + FOR_NET_CARDS_SAFE (card, next) + if (card->driver == &efidriver) + grub_net_card_unregister (card); ++ ++ grub_efi_net_config = NULL; + } + +diff --git a/grub-core/net/efi/dhcp.c b/grub-core/net/efi/dhcp.c +new file mode 100644 +index 00000000000..dbef63d8c08 +--- /dev/null ++++ b/grub-core/net/efi/dhcp.c +@@ -0,0 +1,397 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef GRUB_EFI_NET_DEBUG ++static void ++dhcp4_mode_print (grub_efi_dhcp4_mode_data_t *mode) ++{ ++ switch (mode->state) ++ { ++ case GRUB_EFI_DHCP4_STOPPED: ++ grub_printf ("STATE: STOPPED\n"); ++ break; ++ case GRUB_EFI_DHCP4_INIT: ++ grub_printf ("STATE: INIT\n"); ++ break; ++ case GRUB_EFI_DHCP4_SELECTING: ++ grub_printf ("STATE: SELECTING\n"); ++ break; ++ case GRUB_EFI_DHCP4_REQUESTING: ++ grub_printf ("STATE: REQUESTING\n"); ++ break; ++ case GRUB_EFI_DHCP4_BOUND: ++ grub_printf ("STATE: BOUND\n"); ++ break; ++ case GRUB_EFI_DHCP4_RENEWING: ++ grub_printf ("STATE: RENEWING\n"); ++ break; ++ case GRUB_EFI_DHCP4_REBINDING: ++ grub_printf ("STATE: REBINDING\n"); ++ break; ++ case GRUB_EFI_DHCP4_INIT_REBOOT: ++ grub_printf ("STATE: INIT_REBOOT\n"); ++ break; ++ case GRUB_EFI_DHCP4_REBOOTING: ++ grub_printf ("STATE: REBOOTING\n"); ++ break; ++ default: ++ grub_printf ("STATE: UNKNOWN\n"); ++ break; ++ } ++ ++ grub_printf ("CLIENT_ADDRESS: %u.%u.%u.%u\n", ++ mode->client_address[0], ++ mode->client_address[1], ++ mode->client_address[2], ++ mode->client_address[3]); ++ grub_printf ("SERVER_ADDRESS: %u.%u.%u.%u\n", ++ mode->server_address[0], ++ mode->server_address[1], ++ mode->server_address[2], ++ mode->server_address[3]); ++ grub_printf ("SUBNET_MASK: %u.%u.%u.%u\n", ++ mode->subnet_mask[0], ++ mode->subnet_mask[1], ++ mode->subnet_mask[2], ++ mode->subnet_mask[3]); ++ grub_printf ("ROUTER_ADDRESS: %u.%u.%u.%u\n", ++ mode->router_address[0], ++ mode->router_address[1], ++ mode->router_address[2], ++ mode->router_address[3]); ++} ++#endif ++ ++static grub_efi_ipv4_address_t * ++grub_efi_dhcp4_parse_dns (grub_efi_dhcp4_protocol_t *dhcp4, grub_efi_dhcp4_packet_t *reply_packet) ++{ ++ grub_efi_dhcp4_packet_option_t **option_list; ++ grub_efi_status_t status; ++ grub_efi_uint32_t option_count = 0; ++ grub_efi_uint32_t i; ++ ++ status = efi_call_4 (dhcp4->parse, dhcp4, reply_packet, &option_count, NULL); ++ ++ if (status != GRUB_EFI_BUFFER_TOO_SMALL) ++ return NULL; ++ ++ option_list = grub_malloc (option_count * sizeof(*option_list)); ++ if (!option_list) ++ return NULL; ++ ++ status = efi_call_4 (dhcp4->parse, dhcp4, reply_packet, &option_count, option_list); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_free (option_list); ++ return NULL; ++ } ++ ++ for (i = 0; i < option_count; ++i) ++ { ++ if (option_list[i]->op_code == 6) ++ { ++ grub_efi_ipv4_address_t *dns_address; ++ ++ if (((option_list[i]->length & 0x3) != 0) || (option_list[i]->length == 0)) ++ continue; ++ ++ /* We only contact primary dns */ ++ dns_address = grub_malloc (sizeof (*dns_address)); ++ if (!dns_address) ++ { ++ grub_free (option_list); ++ return NULL; ++ } ++ grub_memcpy (dns_address, option_list[i]->data, sizeof (dns_address)); ++ grub_free (option_list); ++ return dns_address; ++ } ++ } ++ ++ grub_free (option_list); ++ return NULL; ++} ++ ++#if 0 ++/* Somehow this doesn't work ... */ ++static grub_err_t ++grub_cmd_efi_bootp (struct grub_command *cmd __attribute__ ((unused)), ++ int argc __attribute__ ((unused)), ++ char **args __attribute__ ((unused))) ++{ ++ struct grub_efi_net_device *dev; ++ for (dev = net_devices; dev; dev = dev->next) ++ { ++ grub_efi_pxe_t *pxe = dev->ip4_pxe; ++ grub_efi_pxe_mode_t *mode = pxe->mode; ++ grub_efi_status_t status; ++ ++ if (!mode->started) ++ { ++ status = efi_call_2 (pxe->start, pxe, 0); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ grub_printf ("Couldn't start PXE\n"); ++ } ++ ++ status = efi_call_2 (pxe->dhcp, pxe, 0); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_printf ("dhcp4 configure failed, %d\n", (int)status); ++ continue; ++ } ++ ++ dev->prefer_ip6 = 0; ++ } ++ ++ return GRUB_ERR_NONE; ++} ++#endif ++ ++static grub_err_t ++grub_cmd_efi_bootp (struct grub_command *cmd __attribute__ ((unused)), ++ int argc, ++ char **args) ++{ ++ struct grub_efi_net_device *netdev; ++ ++ for (netdev = net_devices; netdev; netdev = netdev->next) ++ { ++ grub_efi_status_t status; ++ grub_efi_dhcp4_mode_data_t mode; ++ grub_efi_dhcp4_config_data_t config; ++ grub_efi_dhcp4_packet_option_t *options; ++ grub_efi_ipv4_address_t *dns_address; ++ grub_efi_net_ip_manual_address_t net_ip; ++ grub_efi_net_ip_address_t ip_addr; ++ grub_efi_net_interface_t *inf = NULL; ++ ++ if (argc > 0 && grub_strcmp (netdev->card_name, args[0]) != 0) ++ continue; ++ ++ grub_memset (&config, 0, sizeof(config)); ++ ++ config.option_count = 1; ++ options = grub_malloc (sizeof(*options) + 2); ++ /* Parameter request list */ ++ options->op_code = 55; ++ options->length = 3; ++ /* subnet mask */ ++ options->data[0] = 1; ++ /* router */ ++ options->data[1] = 3; ++ /* DNS */ ++ options->data[2] = 6; ++ config.option_list = &options; ++ ++ /* FIXME: What if the dhcp has bounded */ ++ status = efi_call_2 (netdev->dhcp4->configure, netdev->dhcp4, &config); ++ grub_free (options); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_printf ("dhcp4 configure failed, %d\n", (int)status); ++ continue; ++ } ++ ++ status = efi_call_2 (netdev->dhcp4->start, netdev->dhcp4, NULL); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_printf ("dhcp4 start failed, %d\n", (int)status); ++ continue; ++ } ++ ++ status = efi_call_2 (netdev->dhcp4->get_mode_data, netdev->dhcp4, &mode); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_printf ("dhcp4 get mode failed, %d\n", (int)status); ++ continue; ++ } ++ ++#ifdef GRUB_EFI_NET_DEBUG ++ dhcp4_mode_print (&mode); ++#endif ++ ++ for (inf = netdev->net_interfaces; inf; inf = inf->next) ++ if (inf->prefer_ip6 == 0) ++ break; ++ ++ grub_memcpy (net_ip.ip4.address, mode.client_address, sizeof (net_ip.ip4.address)); ++ grub_memcpy (net_ip.ip4.subnet_mask, mode.subnet_mask, sizeof (net_ip.ip4.subnet_mask)); ++ ++ if (!inf) ++ { ++ char *name = grub_xasprintf ("%s:dhcp", netdev->card_name); ++ ++ net_ip.is_ip6 = 0; ++ inf = grub_efi_net_create_interface (netdev, ++ name, ++ &net_ip, ++ 1); ++ grub_free (name); ++ } ++ else ++ { ++ efi_net_interface_set_address (inf, &net_ip, 1); ++ } ++ ++ grub_memcpy (ip_addr.ip4, mode.router_address, sizeof (ip_addr.ip4)); ++ efi_net_interface_set_gateway (inf, &ip_addr); ++ ++ dns_address = grub_efi_dhcp4_parse_dns (netdev->dhcp4, mode.reply_packet); ++ if (dns_address) ++ efi_net_interface_set_dns (inf, (grub_efi_net_ip_address_t *)&dns_address); ++ ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ ++ ++static grub_err_t ++grub_cmd_efi_bootp6 (struct grub_command *cmd __attribute__ ((unused)), ++ int argc, ++ char **args) ++{ ++ struct grub_efi_net_device *dev; ++ grub_efi_uint32_t ia_id; ++ ++ for (dev = net_devices, ia_id = 0; dev; dev = dev->next, ia_id++) ++ { ++ grub_efi_dhcp6_config_data_t config; ++ grub_efi_dhcp6_packet_option_t *option_list[1]; ++ grub_efi_dhcp6_packet_option_t *opt; ++ grub_efi_status_t status; ++ grub_efi_dhcp6_mode_data_t mode; ++ grub_efi_dhcp6_retransmission_t retrans; ++ grub_efi_net_ip_manual_address_t net_ip; ++ grub_efi_boot_services_t *b = grub_efi_system_table->boot_services; ++ grub_efi_net_interface_t *inf = NULL; ++ ++ if (argc > 0 && grub_strcmp (dev->card_name, args[0]) != 0) ++ continue; ++ ++ opt = grub_malloc (sizeof(*opt) + 2 * sizeof (grub_efi_uint16_t)); ++ ++#define GRUB_EFI_DHCP6_OPT_ORO 6 ++ ++ opt->op_code = grub_cpu_to_be16_compile_time (GRUB_EFI_DHCP6_OPT_ORO); ++ opt->op_len = grub_cpu_to_be16_compile_time (2 * sizeof (grub_efi_uint16_t)); ++ ++#define GRUB_EFI_DHCP6_OPT_BOOT_FILE_URL 59 ++#define GRUB_EFI_DHCP6_OPT_DNS_SERVERS 23 ++ ++ grub_set_unaligned16 (opt->data, grub_cpu_to_be16_compile_time(GRUB_EFI_DHCP6_OPT_BOOT_FILE_URL)); ++ grub_set_unaligned16 (opt->data + 1 * sizeof (grub_efi_uint16_t), ++ grub_cpu_to_be16_compile_time(GRUB_EFI_DHCP6_OPT_DNS_SERVERS)); ++ ++ option_list[0] = opt; ++ retrans.irt = 4; ++ retrans.mrc = 4; ++ retrans.mrt = 32; ++ retrans.mrd = 60; ++ ++ config.dhcp6_callback = NULL; ++ config.callback_context = NULL; ++ config.option_count = 1; ++ config.option_list = option_list; ++ config.ia_descriptor.ia_id = ia_id; ++ config.ia_descriptor.type = GRUB_EFI_DHCP6_IA_TYPE_NA; ++ config.ia_info_event = NULL; ++ config.reconfigure_accept = 0; ++ config.rapid_commit = 0; ++ config.solicit_retransmission = &retrans; ++ ++ status = efi_call_2 (dev->dhcp6->configure, dev->dhcp6, &config); ++ grub_free (opt); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_printf ("dhcp6 configure failed, %d\n", (int)status); ++ continue; ++ } ++ status = efi_call_1 (dev->dhcp6->start, dev->dhcp6); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_printf ("dhcp6 start failed, %d\n", (int)status); ++ continue; ++ } ++ ++ status = efi_call_3 (dev->dhcp6->get_mode_data, dev->dhcp6, &mode, NULL); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_printf ("dhcp4 get mode failed, %d\n", (int)status); ++ continue; ++ } ++ ++ for (inf = dev->net_interfaces; inf; inf = inf->next) ++ if (inf->prefer_ip6 == 1) ++ break; ++ ++ grub_memcpy (net_ip.ip6.address, mode.ia->ia_address[0].ip_address, sizeof (net_ip.ip6.address)); ++ net_ip.ip6.prefix_length = 64; ++ net_ip.ip6.is_anycast = 0; ++ net_ip.is_ip6 = 1; ++ ++ if (!inf) ++ { ++ char *name = grub_xasprintf ("%s:dhcp", dev->card_name); ++ ++ inf = grub_efi_net_create_interface (dev, ++ name, ++ &net_ip, ++ 1); ++ grub_free (name); ++ } ++ else ++ { ++ efi_net_interface_set_address (inf, &net_ip, 1); ++ } ++ ++ { ++ grub_efi_uint32_t count = 0; ++ grub_efi_dhcp6_packet_option_t **options = NULL; ++ grub_efi_uint32_t i; ++ ++ status = efi_call_4 (dev->dhcp6->parse, dev->dhcp6, mode.ia->reply_packet, &count, NULL); ++ ++ if (status == GRUB_EFI_BUFFER_TOO_SMALL && count) ++ { ++ options = grub_malloc (count * sizeof(*options)); ++ status = efi_call_4 (dev->dhcp6->parse, dev->dhcp6, mode.ia->reply_packet, &count, options); ++ } ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ if (options) ++ grub_free (options); ++ continue; ++ } ++ ++ for (i = 0; i < count; ++i) ++ { ++ if (options[i]->op_code == grub_cpu_to_be16_compile_time(GRUB_EFI_DHCP6_OPT_DNS_SERVERS)) ++ { ++ grub_efi_net_ip_address_t dns; ++ grub_memcpy (dns.ip6, options[i]->data, sizeof(net_ip.ip6)); ++ efi_net_interface_set_dns (inf, &dns); ++ break; ++ } ++ } ++ ++ if (options) ++ grub_free (options); ++ } ++ ++ efi_call_1 (b->free_pool, mode.client_id); ++ efi_call_1 (b->free_pool, mode.ia); ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ ++grub_command_func_t grub_efi_net_bootp = grub_cmd_efi_bootp; ++grub_command_func_t grub_efi_net_bootp6 = grub_cmd_efi_bootp6; +diff --git a/grub-core/net/efi/efi_netfs.c b/grub-core/net/efi/efi_netfs.c +new file mode 100644 +index 00000000000..ef371d885ea +--- /dev/null ++++ b/grub-core/net/efi/efi_netfs.c +@@ -0,0 +1,57 @@ ++#include ++#include ++#define EFI_NET_CMD_PREFIX "net_efi" ++#include ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++static grub_command_t cmd_efi_lsroutes; ++static grub_command_t cmd_efi_lscards; ++static grub_command_t cmd_efi_lsaddrs; ++static grub_command_t cmd_efi_addaddr; ++static grub_command_t cmd_efi_bootp; ++static grub_command_t cmd_efi_bootp6; ++ ++static int initialized; ++ ++GRUB_MOD_INIT(efi_netfs) ++{ ++ if (grub_net_open) ++ return; ++ ++ if (grub_efi_net_fs_init ()) ++ { ++ cmd_efi_lsroutes = grub_register_command ("net_efi_ls_routes", grub_efi_net_list_routes, ++ "", N_("list network routes")); ++ cmd_efi_lscards = grub_register_command ("net_efi_ls_cards", grub_efi_net_list_cards, ++ "", N_("list network cards")); ++ cmd_efi_lsaddrs = grub_register_command ("net_efi_ls_addr", grub_efi_net_list_addrs, ++ "", N_("list network addresses")); ++ cmd_efi_addaddr = grub_register_command ("net_efi_add_addr", grub_efi_net_add_addr, ++ N_("SHORTNAME CARD ADDRESS [HWADDRESS]"), ++ N_("Add a network address.")); ++ cmd_efi_bootp = grub_register_command ("net_efi_bootp", grub_efi_net_bootp, ++ N_("[CARD]"), ++ N_("perform a bootp autoconfiguration")); ++ cmd_efi_bootp6 = grub_register_command ("net_efi_bootp6", grub_efi_net_bootp6, ++ N_("[CARD]"), ++ N_("perform a bootp autoconfiguration")); ++ initialized = 1; ++ } ++} ++ ++GRUB_MOD_FINI(efi_netfs) ++{ ++ if (initialized) ++ { ++ grub_unregister_command (cmd_efi_lsroutes); ++ grub_unregister_command (cmd_efi_lscards); ++ grub_unregister_command (cmd_efi_lsaddrs); ++ grub_unregister_command (cmd_efi_addaddr); ++ grub_unregister_command (cmd_efi_bootp); ++ grub_unregister_command (cmd_efi_bootp6); ++ grub_efi_net_fs_fini (); ++ initialized = 0; ++ return; ++ } ++} +diff --git a/grub-core/net/efi/http.c b/grub-core/net/efi/http.c +new file mode 100644 +index 00000000000..3f61fd2fa5b +--- /dev/null ++++ b/grub-core/net/efi/http.c +@@ -0,0 +1,419 @@ ++ ++#include ++#include ++#include ++#include ++#include ++ ++static void ++http_configure (struct grub_efi_net_device *dev, int prefer_ip6) ++{ ++ grub_efi_http_config_data_t http_config; ++ grub_efi_httpv4_access_point_t httpv4_node; ++ grub_efi_httpv6_access_point_t httpv6_node; ++ grub_efi_status_t status; ++ ++ grub_efi_http_t *http = dev->http; ++ ++ grub_memset (&http_config, 0, sizeof(http_config)); ++ http_config.http_version = GRUB_EFI_HTTPVERSION11; ++ http_config.timeout_millisec = 5000; ++ ++ if (prefer_ip6) ++ { ++ grub_efi_uintn_t sz; ++ grub_efi_ip6_config_manual_address_t manual_address; ++ ++ http_config.local_address_is_ipv6 = 1; ++ sz = sizeof (manual_address); ++ status = efi_call_4 (dev->ip6_config->get_data, dev->ip6_config, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS, ++ &sz, &manual_address); ++ ++ if (status == GRUB_EFI_NOT_FOUND) ++ { ++ grub_printf ("The MANUAL ADDRESS is not found\n"); ++ } ++ ++ /* FIXME: The manual interface would return BUFFER TOO SMALL !!! */ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_printf ("??? %d\n",(int) status); ++ return; ++ } ++ ++ grub_memcpy (httpv6_node.local_address, manual_address.address, sizeof (httpv6_node.local_address)); ++ httpv6_node.local_port = 0; ++ http_config.access_point.ipv6_node = &httpv6_node; ++ } ++ else ++ { ++ http_config.local_address_is_ipv6 = 0; ++ grub_memset (&httpv4_node, 0, sizeof(httpv4_node)); ++ httpv4_node.use_default_address = 1; ++ ++ /* Use random port here */ ++ /* See TcpBind() in edk2/NetworkPkg/TcpDxe/TcpDispatcher.c */ ++ httpv4_node.local_port = 0; ++ http_config.access_point.ipv4_node = &httpv4_node; ++ } ++ ++ status = efi_call_2 (http->configure, http, &http_config); ++ ++ if (status == GRUB_EFI_ALREADY_STARTED) ++ { ++ /* XXX: This hangs HTTPS boot */ ++#if 0 ++ if (efi_call_2 (http->configure, http, NULL) != GRUB_EFI_SUCCESS) ++ { ++ grub_error (GRUB_ERR_IO, N_("couldn't reset http instance")); ++ grub_print_error (); ++ return; ++ } ++ status = efi_call_2 (http->configure, http, &http_config); ++#endif ++ return; ++ } ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_error (GRUB_ERR_IO, N_("couldn't configure http protocol, reason: %d"), (int)status); ++ grub_print_error (); ++ return ; ++ } ++} ++ ++static grub_efi_boolean_t request_callback_done; ++static grub_efi_boolean_t response_callback_done; ++ ++static void ++grub_efi_http_request_callback (grub_efi_event_t event __attribute__ ((unused)), ++ void *context __attribute__ ((unused))) ++{ ++ request_callback_done = 1; ++} ++ ++static void ++grub_efi_http_response_callback (grub_efi_event_t event __attribute__ ((unused)), ++ void *context __attribute__ ((unused))) ++{ ++ response_callback_done = 1; ++} ++ ++static grub_err_t ++efihttp_request (grub_efi_http_t *http, char *server, char *name, int use_https, int headeronly, grub_off_t *file_size) ++{ ++ grub_efi_http_request_data_t request_data; ++ grub_efi_http_message_t request_message; ++ grub_efi_http_token_t request_token; ++ grub_efi_http_response_data_t response_data; ++ grub_efi_http_message_t response_message; ++ grub_efi_http_token_t response_token; ++ grub_efi_http_header_t request_headers[3]; ++ ++ grub_efi_status_t status; ++ grub_efi_boot_services_t *b = grub_efi_system_table->boot_services; ++ char *url = NULL; ++ ++ request_headers[0].field_name = (grub_efi_char8_t *)"Host"; ++ request_headers[0].field_value = (grub_efi_char8_t *)server; ++ request_headers[1].field_name = (grub_efi_char8_t *)"Accept"; ++ request_headers[1].field_value = (grub_efi_char8_t *)"*/*"; ++ request_headers[2].field_name = (grub_efi_char8_t *)"User-Agent"; ++ request_headers[2].field_value = (grub_efi_char8_t *)"UefiHttpBoot/1.0"; ++ ++ { ++ grub_efi_ipv6_address_t address; ++ const char *rest; ++ grub_efi_char16_t *ucs2_url; ++ grub_size_t url_len, ucs2_url_len; ++ const char *protocol = (use_https == 1) ? "https" : "http"; ++ ++ if (grub_efi_string_to_ip6_address (server, &address, &rest) && *rest == 0) ++ url = grub_xasprintf ("%s://[%s]%s", protocol, server, name); ++ else ++ url = grub_xasprintf ("%s://%s%s", protocol, server, name); ++ ++ if (!url) ++ { ++ return grub_errno; ++ } ++ ++ url_len = grub_strlen (url); ++ ucs2_url_len = url_len * GRUB_MAX_UTF16_PER_UTF8; ++ ucs2_url = grub_malloc ((ucs2_url_len + 1) * sizeof (ucs2_url[0])); ++ ++ if (!ucs2_url) ++ { ++ grub_free (url); ++ return grub_errno; ++ } ++ ++ ucs2_url_len = grub_utf8_to_utf16 (ucs2_url, ucs2_url_len, (grub_uint8_t *)url, url_len, NULL); /* convert string format from ascii to usc2 */ ++ ucs2_url[ucs2_url_len] = 0; ++ grub_free (url); ++ request_data.url = ucs2_url; ++ } ++ ++ request_data.method = (headeronly > 0) ? GRUB_EFI_HTTPMETHODHEAD : GRUB_EFI_HTTPMETHODGET; ++ ++ request_message.data.request = &request_data; ++ request_message.header_count = 3; ++ request_message.headers = request_headers; ++ request_message.body_length = 0; ++ request_message.body = NULL; ++ ++ /* request token */ ++ request_token.event = NULL; ++ request_token.status = GRUB_EFI_NOT_READY; ++ request_token.message = &request_message; ++ ++ request_callback_done = 0; ++ status = efi_call_5 (b->create_event, ++ GRUB_EFI_EVT_NOTIFY_SIGNAL, ++ GRUB_EFI_TPL_CALLBACK, ++ grub_efi_http_request_callback, ++ NULL, ++ &request_token.event); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_free (request_data.url); ++ return grub_error (GRUB_ERR_IO, "Fail to create an event! status=0x%x\n", status); ++ } ++ ++ status = efi_call_2 (http->request, http, &request_token); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ efi_call_1 (b->close_event, request_token.event); ++ grub_free (request_data.url); ++ return grub_error (GRUB_ERR_IO, "Fail to send a request! status=0x%x\n", status); ++ } ++ /* TODO: Add Timeout */ ++ while (!request_callback_done) ++ efi_call_1(http->poll, http); ++ ++ response_data.status_code = GRUB_EFI_HTTP_STATUS_UNSUPPORTED_STATUS; ++ response_message.data.response = &response_data; ++ /* herader_count will be updated by the HTTP driver on response */ ++ response_message.header_count = 0; ++ /* headers will be populated by the driver on response */ ++ response_message.headers = NULL; ++ /* use zero BodyLength to only receive the response headers */ ++ response_message.body_length = 0; ++ response_message.body = NULL; ++ response_token.event = NULL; ++ ++ status = efi_call_5 (b->create_event, ++ GRUB_EFI_EVT_NOTIFY_SIGNAL, ++ GRUB_EFI_TPL_CALLBACK, ++ grub_efi_http_response_callback, ++ NULL, ++ &response_token.event); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ efi_call_1 (b->close_event, request_token.event); ++ grub_free (request_data.url); ++ return grub_error (GRUB_ERR_IO, "Fail to create an event! status=0x%x\n", status); ++ } ++ ++ response_token.status = GRUB_EFI_SUCCESS; ++ response_token.message = &response_message; ++ ++ /* wait for HTTP response */ ++ response_callback_done = 0; ++ status = efi_call_2 (http->response, http, &response_token); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ efi_call_1 (b->close_event, response_token.event); ++ efi_call_1 (b->close_event, request_token.event); ++ grub_free (request_data.url); ++ return grub_error (GRUB_ERR_IO, "Fail to receive a response! status=%d\n", (int)status); ++ } ++ ++ /* TODO: Add Timeout */ ++ while (!response_callback_done) ++ efi_call_1 (http->poll, http); ++ ++ if (response_message.data.response->status_code != GRUB_EFI_HTTP_STATUS_200_OK) ++ { ++ grub_efi_http_status_code_t status_code = response_message.data.response->status_code; ++ ++ if (response_message.headers) ++ efi_call_1 (b->free_pool, response_message.headers); ++ efi_call_1 (b->close_event, response_token.event); ++ efi_call_1 (b->close_event, request_token.event); ++ grub_free (request_data.url); ++ if (status_code == GRUB_EFI_HTTP_STATUS_404_NOT_FOUND) ++ { ++ return grub_error (GRUB_ERR_FILE_NOT_FOUND, _("file `%s' not found"), name); ++ } ++ else ++ { ++ return grub_error (GRUB_ERR_NET_UNKNOWN_ERROR, ++ _("unsupported uefi http status code 0x%x"), status_code); ++ } ++ } ++ ++ if (file_size) ++ { ++ int i; ++ /* parse the length of the file from the ContentLength header */ ++ for (*file_size = 0, i = 0; i < (int)response_message.header_count; ++i) ++ { ++ if (!grub_strcmp((const char*)response_message.headers[i].field_name, "Content-Length")) ++ { ++ *file_size = grub_strtoul((const char*)response_message.headers[i].field_value, 0, 10); ++ break; ++ } ++ } ++ } ++ ++ if (response_message.headers) ++ efi_call_1 (b->free_pool, response_message.headers); ++ efi_call_1 (b->close_event, response_token.event); ++ efi_call_1 (b->close_event, request_token.event); ++ grub_free (request_data.url); ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_ssize_t ++efihttp_read (struct grub_efi_net_device *dev, ++ char *buf, ++ grub_size_t len) ++{ ++ grub_efi_http_message_t response_message; ++ grub_efi_http_token_t response_token; ++ ++ grub_efi_status_t status; ++ grub_size_t sum = 0; ++ grub_efi_boot_services_t *b = grub_efi_system_table->boot_services; ++ grub_efi_http_t *http = dev->http; ++ ++ if (!len) ++ { ++ grub_error (GRUB_ERR_BUG, "Invalid arguments to EFI HTTP Read"); ++ return -1; ++ } ++ ++ efi_call_5 (b->create_event, ++ GRUB_EFI_EVT_NOTIFY_SIGNAL, ++ GRUB_EFI_TPL_CALLBACK, ++ grub_efi_http_response_callback, ++ NULL, ++ &response_token.event); ++ ++ while (len) ++ { ++ response_message.data.response = NULL; ++ response_message.header_count = 0; ++ response_message.headers = NULL; ++ response_message.body_length = len; ++ response_message.body = buf; ++ ++ response_token.message = &response_message; ++ response_token.status = GRUB_EFI_NOT_READY; ++ ++ response_callback_done = 0; ++ ++ status = efi_call_2 (http->response, http, &response_token); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ efi_call_1 (b->close_event, response_token.event); ++ grub_error (GRUB_ERR_IO, "Error! status=%d\n", (int)status); ++ return -1; ++ } ++ ++ while (!response_callback_done) ++ efi_call_1(http->poll, http); ++ ++ sum += response_message.body_length; ++ buf += response_message.body_length; ++ len -= response_message.body_length; ++ } ++ ++ efi_call_1 (b->close_event, response_token.event); ++ ++ return sum; ++} ++ ++static grub_err_t ++grub_efihttp_open (struct grub_efi_net_device *dev, ++ int prefer_ip6 __attribute__ ((unused)), ++ grub_file_t file, ++ const char *filename __attribute__ ((unused)), ++ int type) ++{ ++ grub_err_t err; ++ grub_off_t size; ++ char *buf; ++ ++ err = efihttp_request (dev->http, file->device->net->server, file->device->net->name, type, 1, 0); ++ if (err != GRUB_ERR_NONE) ++ return err; ++ ++ err = efihttp_request (dev->http, file->device->net->server, file->device->net->name, type, 0, &size); ++ if (err != GRUB_ERR_NONE) ++ return err; ++ ++ buf = grub_malloc (size); ++ efihttp_read (dev, buf, size); ++ ++ file->size = size; ++ file->data = buf; ++ file->not_easily_seekable = 0; ++ file->device->net->offset = 0; ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_efihttp_close (struct grub_efi_net_device *dev __attribute__ ((unused)), ++ int prefer_ip6 __attribute__ ((unused)), ++ grub_file_t file) ++{ ++ if (file->data) ++ grub_free (file->data); ++ ++ file->data = 0; ++ file->offset = 0; ++ file->size = 0; ++ file->device->net->offset = 0; ++ return GRUB_ERR_NONE; ++} ++ ++static grub_ssize_t ++grub_efihttp_read (struct grub_efi_net_device *dev __attribute__((unused)), ++ int prefer_ip6 __attribute__((unused)), ++ grub_file_t file, ++ char *buf, ++ grub_size_t len) ++{ ++ grub_size_t r = len; ++ ++ if (!file->data || !buf || !len) ++ return 0; ++ ++ if ((file->device->net->offset + len) > file->size) ++ r = file->size - file->device->net->offset; ++ ++ if (r) ++ { ++ grub_memcpy (buf, (char *)file->data + file->device->net->offset, r); ++ file->device->net->offset += r; ++ } ++ ++ return r; ++} ++ ++struct grub_efi_net_io io_http = ++ { ++ .configure = http_configure, ++ .open = grub_efihttp_open, ++ .read = grub_efihttp_read, ++ .close = grub_efihttp_close ++ }; +diff --git a/grub-core/net/efi/ip4_config.c b/grub-core/net/efi/ip4_config.c +new file mode 100644 +index 00000000000..b711a5d9457 +--- /dev/null ++++ b/grub-core/net/efi/ip4_config.c +@@ -0,0 +1,398 @@ ++ ++#include ++#include ++#include ++#include ++#include ++ ++char * ++grub_efi_hw_address_to_string (grub_efi_uint32_t hw_address_size, grub_efi_mac_address_t hw_address) ++{ ++ char *hw_addr, *p; ++ int sz, s; ++ int i; ++ ++ sz = (int)hw_address_size * (sizeof ("XX:") - 1) + 1; ++ ++ hw_addr = grub_malloc (sz); ++ if (!hw_addr) ++ return NULL; ++ ++ p = hw_addr; ++ s = sz; ++ for (i = 0; i < (int)hw_address_size; i++) ++ { ++ grub_snprintf (p, sz, "%02x:", hw_address[i]); ++ p += sizeof ("XX:") - 1; ++ s -= sizeof ("XX:") - 1; ++ } ++ ++ hw_addr[sz - 2] = '\0'; ++ return hw_addr; ++} ++ ++char * ++grub_efi_ip4_address_to_string (grub_efi_ipv4_address_t *address) ++{ ++ char *addr; ++ ++ addr = grub_malloc (sizeof ("XXX.XXX.XXX.XXX")); ++ if (!addr) ++ return NULL; ++ ++ /* FIXME: Use grub_xasprintf ? */ ++ grub_snprintf (addr, ++ sizeof ("XXX.XXX.XXX.XXX"), ++ "%u.%u.%u.%u", ++ (*address)[0], ++ (*address)[1], ++ (*address)[2], ++ (*address)[3]); ++ ++ return addr; ++} ++ ++int ++grub_efi_string_to_ip4_address (const char *val, grub_efi_ipv4_address_t *address, const char **rest) ++{ ++ grub_uint32_t newip = 0; ++ int i; ++ const char *ptr = val; ++ ++ for (i = 0; i < 4; i++) ++ { ++ unsigned long t; ++ t = grub_strtoul (ptr, (char **) &ptr, 0); ++ if (grub_errno) ++ { ++ grub_errno = GRUB_ERR_NONE; ++ return 0; ++ } ++ if (*ptr != '.' && i == 0) ++ { ++ /* XXX: t is in host byte order */ ++ newip = t; ++ break; ++ } ++ if (t & ~0xff) ++ return 0; ++ newip <<= 8; ++ newip |= t; ++ if (i != 3 && *ptr != '.') ++ return 0; ++ ptr++; ++ } ++ ++ newip = grub_cpu_to_be32 (newip); ++ ++ grub_memcpy (address, &newip, sizeof(*address)); ++ ++ if (rest) ++ *rest = (ptr - 1); ++ return 1; ++} ++ ++static grub_efi_ip4_config2_interface_info_t * ++efi_ip4_config_interface_info (grub_efi_ip4_config2_protocol_t *ip4_config) ++{ ++ grub_efi_uintn_t sz; ++ grub_efi_status_t status; ++ grub_efi_ip4_config2_interface_info_t *interface_info; ++ ++ sz = sizeof (*interface_info) + sizeof (*interface_info->route_table); ++ interface_info = grub_malloc (sz); ++ if (!interface_info) ++ return NULL; ++ ++ status = efi_call_4 (ip4_config->get_data, ip4_config, ++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_INTERFACEINFO, ++ &sz, interface_info); ++ ++ if (status == GRUB_EFI_BUFFER_TOO_SMALL) ++ { ++ grub_free (interface_info); ++ interface_info = grub_malloc (sz); ++ status = efi_call_4 (ip4_config->get_data, ip4_config, ++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_INTERFACEINFO, ++ &sz, interface_info); ++ } ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_free (interface_info); ++ return NULL; ++ } ++ ++ return interface_info; ++} ++ ++static grub_efi_ip4_config2_manual_address_t * ++efi_ip4_config_manual_address (grub_efi_ip4_config2_protocol_t *ip4_config) ++{ ++ grub_efi_uintn_t sz; ++ grub_efi_status_t status; ++ grub_efi_ip4_config2_manual_address_t *manual_address; ++ ++ sz = sizeof (*manual_address); ++ manual_address = grub_malloc (sz); ++ if (!manual_address) ++ return NULL; ++ ++ status = efi_call_4 (ip4_config->get_data, ip4_config, ++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS, ++ &sz, manual_address); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_free (manual_address); ++ return NULL; ++ } ++ ++ return manual_address; ++} ++ ++char * ++grub_efi_ip4_interface_name (struct grub_efi_net_device *dev) ++{ ++ grub_efi_ip4_config2_interface_info_t *interface_info; ++ char *name; ++ ++ interface_info = efi_ip4_config_interface_info (dev->ip4_config); ++ ++ if (!interface_info) ++ return NULL; ++ ++ name = grub_malloc (GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE ++ * GRUB_MAX_UTF8_PER_UTF16 + 1); ++ *grub_utf16_to_utf8 ((grub_uint8_t *)name, interface_info->name, ++ GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE) = 0; ++ grub_free (interface_info); ++ return name; ++} ++ ++static char * ++grub_efi_ip4_interface_hw_address (struct grub_efi_net_device *dev) ++{ ++ grub_efi_ip4_config2_interface_info_t *interface_info; ++ char *hw_addr; ++ ++ interface_info = efi_ip4_config_interface_info (dev->ip4_config); ++ ++ if (!interface_info) ++ return NULL; ++ ++ hw_addr = grub_efi_hw_address_to_string (interface_info->hw_address_size, interface_info->hw_address); ++ grub_free (interface_info); ++ ++ return hw_addr; ++} ++ ++static char * ++grub_efi_ip4_interface_address (struct grub_efi_net_device *dev) ++{ ++ grub_efi_ip4_config2_manual_address_t *manual_address; ++ char *addr; ++ ++ manual_address = efi_ip4_config_manual_address (dev->ip4_config); ++ ++ if (!manual_address) ++ return NULL; ++ ++ addr = grub_efi_ip4_address_to_string (&manual_address->address); ++ grub_free (manual_address); ++ return addr; ++} ++ ++ ++static int ++address_mask_size (grub_efi_ipv4_address_t *address) ++{ ++ grub_uint8_t i; ++ grub_uint32_t u32_addr = grub_be_to_cpu32 (grub_get_unaligned32 (address)); ++ ++ if (u32_addr == 0) ++ return 0; ++ ++ for (i = 0; i < 32 ; ++i) ++ { ++ if (u32_addr == ((0xffffffff >> i) << i)) ++ return (32 - i); ++ } ++ ++ return -1; ++} ++ ++static char ** ++grub_efi_ip4_interface_route_table (struct grub_efi_net_device *dev) ++{ ++ grub_efi_ip4_config2_interface_info_t *interface_info; ++ char **ret; ++ int i, id; ++ ++ interface_info = efi_ip4_config_interface_info (dev->ip4_config); ++ if (!interface_info) ++ return NULL; ++ ++ ret = grub_malloc (sizeof (*ret) * (interface_info->route_table_size + 1)); ++ ++ if (!ret) ++ { ++ grub_free (interface_info); ++ return NULL; ++ } ++ ++ id = 0; ++ for (i = 0; i < (int)interface_info->route_table_size; i++) ++ { ++ char *subnet, *gateway, *mask; ++ grub_uint32_t u32_subnet, u32_gateway; ++ int mask_size; ++ grub_efi_ip4_route_table_t *route_table = interface_info->route_table + i; ++ grub_efi_net_interface_t *inf; ++ char *interface_name = NULL; ++ ++ for (inf = dev->net_interfaces; inf; inf = inf->next) ++ if (!inf->prefer_ip6) ++ interface_name = inf->name; ++ ++ u32_gateway = grub_get_unaligned32 (&route_table->gateway_address); ++ gateway = grub_efi_ip4_address_to_string (&route_table->gateway_address); ++ u32_subnet = grub_get_unaligned32 (&route_table->subnet_address); ++ subnet = grub_efi_ip4_address_to_string (&route_table->subnet_address); ++ mask_size = address_mask_size (&route_table->subnet_mask); ++ mask = grub_efi_ip4_address_to_string (&route_table->subnet_mask); ++ if (u32_subnet && !u32_gateway && interface_name) ++ ret[id++] = grub_xasprintf ("%s:local %s/%d %s", dev->card_name, subnet, mask_size, interface_name); ++ else if (u32_subnet && u32_gateway) ++ ret[id++] = grub_xasprintf ("%s:gw %s/%d gw %s", dev->card_name, subnet, mask_size, gateway); ++ else if (!u32_subnet && u32_gateway) ++ ret[id++] = grub_xasprintf ("%s:default %s/%d gw %s", dev->card_name, subnet, mask_size, gateway); ++ grub_free (subnet); ++ grub_free (gateway); ++ grub_free (mask); ++ } ++ ++ ret[id] = NULL; ++ grub_free (interface_info); ++ return ret; ++} ++ ++static grub_efi_net_interface_t * ++grub_efi_ip4_interface_match (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *ip_address) ++{ ++ grub_efi_ip4_config2_interface_info_t *interface_info; ++ grub_efi_net_interface_t *inf; ++ int i; ++ grub_efi_ipv4_address_t *address = &ip_address->ip4; ++ ++ interface_info = efi_ip4_config_interface_info (dev->ip4_config); ++ if (!interface_info) ++ return NULL; ++ ++ for (i = 0; i < (int)interface_info->route_table_size; i++) ++ { ++ grub_efi_ip4_route_table_t *route_table = interface_info->route_table + i; ++ grub_uint32_t u32_address, u32_mask, u32_subnet; ++ ++ u32_address = grub_get_unaligned32 (address); ++ u32_subnet = grub_get_unaligned32 (route_table->subnet_address); ++ u32_mask = grub_get_unaligned32 (route_table->subnet_mask); ++ ++ /* SKIP Default GATEWAY */ ++ if (!u32_subnet && !u32_mask) ++ continue; ++ ++ if ((u32_address & u32_mask) == u32_subnet) ++ { ++ for (inf = dev->net_interfaces; inf; inf = inf->next) ++ if (!inf->prefer_ip6) ++ { ++ grub_free (interface_info); ++ return inf; ++ } ++ } ++ } ++ ++ grub_free (interface_info); ++ return NULL; ++} ++ ++static int ++grub_efi_ip4_interface_set_manual_address (struct grub_efi_net_device *dev, ++ grub_efi_net_ip_manual_address_t *net_ip, ++ int with_subnet) ++{ ++ grub_efi_status_t status; ++ grub_efi_ip4_config2_manual_address_t *address = &net_ip->ip4; ++ ++ if (!with_subnet) ++ { ++ grub_efi_ip4_config2_manual_address_t *manual_address = ++ efi_ip4_config_manual_address (dev->ip4_config); ++ ++ if (manual_address) ++ { ++ grub_memcpy (address->subnet_mask, manual_address->subnet_mask, sizeof(address->subnet_mask)); ++ grub_free (manual_address); ++ } ++ else ++ { ++ /* XXX: */ ++ address->subnet_mask[0] = 0xff; ++ address->subnet_mask[1] = 0xff; ++ address->subnet_mask[2] = 0xff; ++ address->subnet_mask[3] = 0; ++ } ++ } ++ ++ status = efi_call_4 (dev->ip4_config->set_data, dev->ip4_config, ++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS, ++ sizeof(*address), address); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ return 0; ++ ++ return 1; ++} ++ ++static int ++grub_efi_ip4_interface_set_gateway (struct grub_efi_net_device *dev, ++ grub_efi_net_ip_address_t *address) ++{ ++ grub_efi_status_t status; ++ ++ status = efi_call_4 (dev->ip4_config->set_data, dev->ip4_config, ++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_GATEWAY, ++ sizeof (address->ip4), &address->ip4); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ return 0; ++ return 1; ++} ++ ++/* FIXME: Multiple DNS */ ++static int ++grub_efi_ip4_interface_set_dns (struct grub_efi_net_device *dev, ++ grub_efi_net_ip_address_t *address) ++{ ++ grub_efi_status_t status; ++ ++ status = efi_call_4 (dev->ip4_config->set_data, dev->ip4_config, ++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER, ++ sizeof (address->ip4), &address->ip4); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ return 0; ++ return 1; ++} ++ ++grub_efi_net_ip_config_t *efi_net_ip4_config = &(grub_efi_net_ip_config_t) ++ { ++ .get_hw_address = grub_efi_ip4_interface_hw_address, ++ .get_address = grub_efi_ip4_interface_address, ++ .get_route_table = grub_efi_ip4_interface_route_table, ++ .best_interface = grub_efi_ip4_interface_match, ++ .set_address = grub_efi_ip4_interface_set_manual_address, ++ .set_gateway = grub_efi_ip4_interface_set_gateway, ++ .set_dns = grub_efi_ip4_interface_set_dns ++ }; +diff --git a/grub-core/net/efi/ip6_config.c b/grub-core/net/efi/ip6_config.c +new file mode 100644 +index 00000000000..017c4d05bc7 +--- /dev/null ++++ b/grub-core/net/efi/ip6_config.c +@@ -0,0 +1,422 @@ ++#include ++#include ++#include ++#include ++#include ++ ++char * ++grub_efi_ip6_address_to_string (grub_efi_pxe_ipv6_address_t *address) ++{ ++ char *str = grub_malloc (sizeof ("XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX")); ++ char *p; ++ int i; ++ int squash; ++ ++ if (!str) ++ return NULL; ++ ++ p = str; ++ squash = 0; ++ for (i = 0; i < 8; ++i) ++ { ++ grub_uint16_t addr; ++ ++ if (i == 7) ++ squash = 2; ++ ++ addr = grub_get_unaligned16 (address->addr + i * 2); ++ ++ if (grub_be_to_cpu16 (addr)) ++ { ++ char buf[sizeof ("XXXX")]; ++ if (i > 0) ++ *p++ = ':'; ++ grub_snprintf (buf, sizeof (buf), "%x", grub_be_to_cpu16 (addr)); ++ grub_strcpy (p, buf); ++ p += grub_strlen (buf); ++ ++ if (squash == 1) ++ squash = 2; ++ } ++ else ++ { ++ if (squash == 0) ++ { ++ *p++ = ':'; ++ squash = 1; ++ } ++ else if (squash == 2) ++ { ++ *p++ = ':'; ++ *p++ = '0'; ++ } ++ } ++ } ++ *p = '\0'; ++ return str; ++} ++ ++int ++grub_efi_string_to_ip6_address (const char *val, grub_efi_ipv6_address_t *address, 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; ++ if (ptr[0] == ':') ++ ptr++; ++ ++ for (word = 0; word < 8; word++) ++ { ++ unsigned long t; ++ if (*ptr == ':') ++ { ++ quaddot = word; ++ word--; ++ ptr++; ++ continue; ++ } ++ t = grub_strtoul (ptr, (char **) &ptr, 16); ++ if (grub_errno) ++ { ++ grub_errno = GRUB_ERR_NONE; ++ break; ++ } ++ if (t & ~0xffff) ++ return 0; ++ newip[word] = grub_cpu_to_be16 (t); ++ if (*ptr != ':') ++ break; ++ ptr++; ++ } ++ if (quaddot == -1 && word < 7) ++ return 0; ++ if (quaddot != -1) ++ { ++ grub_memmove (&newip[quaddot + 7 - word], &newip[quaddot], ++ (word - quaddot + 1) * sizeof (newip[0])); ++ grub_memset (&newip[quaddot], 0, (7 - word) * sizeof (newip[0])); ++ } ++ grub_memcpy (address, newip, 16); ++ if (bracketed && *ptr == ']') { ++ ptr++; ++ } ++ if (rest) ++ *rest = ptr; ++ return 1; ++} ++ ++static grub_efi_ip6_config_interface_info_t * ++efi_ip6_config_interface_info (grub_efi_ip6_config_protocol_t *ip6_config) ++{ ++ grub_efi_uintn_t sz; ++ grub_efi_status_t status; ++ grub_efi_ip6_config_interface_info_t *interface_info; ++ ++ sz = sizeof (*interface_info) + sizeof (*interface_info->route_table); ++ interface_info = grub_malloc (sz); ++ ++ status = efi_call_4 (ip6_config->get_data, ip6_config, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_INTERFACEINFO, ++ &sz, interface_info); ++ ++ if (status == GRUB_EFI_BUFFER_TOO_SMALL) ++ { ++ grub_free (interface_info); ++ interface_info = grub_malloc (sz); ++ status = efi_call_4 (ip6_config->get_data, ip6_config, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_INTERFACEINFO, ++ &sz, interface_info); ++ } ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_free (interface_info); ++ return NULL; ++ } ++ ++ return interface_info; ++} ++ ++static grub_efi_ip6_config_manual_address_t * ++efi_ip6_config_manual_address (grub_efi_ip6_config_protocol_t *ip6_config) ++{ ++ grub_efi_uintn_t sz; ++ grub_efi_status_t status; ++ grub_efi_ip6_config_manual_address_t *manual_address; ++ ++ sz = sizeof (*manual_address); ++ manual_address = grub_malloc (sz); ++ if (!manual_address) ++ return NULL; ++ ++ status = efi_call_4 (ip6_config->get_data, ip6_config, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS, ++ &sz, manual_address); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_free (manual_address); ++ return NULL; ++ } ++ ++ return manual_address; ++} ++ ++char * ++grub_efi_ip6_interface_name (struct grub_efi_net_device *dev) ++{ ++ grub_efi_ip6_config_interface_info_t *interface_info; ++ char *name; ++ ++ interface_info = efi_ip6_config_interface_info (dev->ip6_config); ++ ++ if (!interface_info) ++ return NULL; ++ ++ name = grub_malloc (GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE ++ * GRUB_MAX_UTF8_PER_UTF16 + 1); ++ *grub_utf16_to_utf8 ((grub_uint8_t *)name, interface_info->name, ++ GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE) = 0; ++ grub_free (interface_info); ++ return name; ++} ++ ++static char * ++grub_efi_ip6_interface_hw_address (struct grub_efi_net_device *dev) ++{ ++ grub_efi_ip6_config_interface_info_t *interface_info; ++ char *hw_addr; ++ ++ interface_info = efi_ip6_config_interface_info (dev->ip6_config); ++ ++ if (!interface_info) ++ return NULL; ++ ++ hw_addr = grub_efi_hw_address_to_string (interface_info->hw_address_size, interface_info->hw_address); ++ grub_free (interface_info); ++ ++ return hw_addr; ++} ++ ++static char * ++grub_efi_ip6_interface_address (struct grub_efi_net_device *dev) ++{ ++ grub_efi_ip6_config_manual_address_t *manual_address; ++ char *addr; ++ ++ manual_address = efi_ip6_config_manual_address (dev->ip6_config); ++ ++ if (!manual_address) ++ return NULL; ++ ++ addr = grub_efi_ip6_address_to_string ((grub_efi_pxe_ipv6_address_t *)&manual_address->address); ++ grub_free (manual_address); ++ return addr; ++} ++ ++static char ** ++grub_efi_ip6_interface_route_table (struct grub_efi_net_device *dev) ++{ ++ grub_efi_ip6_config_interface_info_t *interface_info; ++ char **ret; ++ int i, id; ++ ++ interface_info = efi_ip6_config_interface_info (dev->ip6_config); ++ if (!interface_info) ++ return NULL; ++ ++ ret = grub_malloc (sizeof (*ret) * (interface_info->route_count + 1)); ++ ++ if (!ret) ++ { ++ grub_free (interface_info); ++ return NULL; ++ } ++ ++ id = 0; ++ for (i = 0; i < (int)interface_info->route_count ; i++) ++ { ++ char *gateway, *destination; ++ grub_uint64_t u64_gateway[2]; ++ grub_uint64_t u64_destination[2]; ++ grub_efi_ip6_route_table_t *route_table = interface_info->route_table + i; ++ grub_efi_net_interface_t *inf; ++ char *interface_name = NULL; ++ ++ gateway = grub_efi_ip6_address_to_string (&route_table->gateway); ++ destination = grub_efi_ip6_address_to_string (&route_table->destination); ++ ++ u64_gateway[0] = grub_get_unaligned64 (route_table->gateway.addr); ++ u64_gateway[1] = grub_get_unaligned64 (route_table->gateway.addr + 8); ++ u64_destination[0] = grub_get_unaligned64 (route_table->destination.addr); ++ u64_destination[1] = grub_get_unaligned64 (route_table->destination.addr + 8); ++ ++ for (inf = dev->net_interfaces; inf; inf = inf->next) ++ if (inf->prefer_ip6) ++ interface_name = inf->name; ++ ++ if ((!u64_gateway[0] && !u64_gateway[1]) ++ && (u64_destination[0] || u64_destination[1])) ++ { ++ if (interface_name) ++ { ++ if ((grub_be_to_cpu64 (u64_destination[0]) == 0xfe80000000000000ULL) ++ && (!u64_destination[1]) ++ && (route_table->prefix_length == 64)) ++ ret[id++] = grub_xasprintf ("%s:link %s/%d %s", dev->card_name, destination, route_table->prefix_length, interface_name); ++ else ++ ret[id++] = grub_xasprintf ("%s:local %s/%d %s", dev->card_name, destination, route_table->prefix_length, interface_name); ++ } ++ } ++ else if ((u64_gateway[0] || u64_gateway[1]) ++ && (u64_destination[0] || u64_destination[1])) ++ ret[id++] = grub_xasprintf ("%s:gw %s/%d gw %s", dev->card_name, destination, route_table->prefix_length, gateway); ++ else if ((u64_gateway[0] || u64_gateway[1]) ++ && (!u64_destination[0] && !u64_destination[1])) ++ ret[id++] = grub_xasprintf ("%s:default %s/%d gw %s", dev->card_name, destination, route_table->prefix_length, gateway); ++ ++ grub_free (gateway); ++ grub_free (destination); ++ } ++ ++ ret[id] = NULL; ++ grub_free (interface_info); ++ return ret; ++} ++ ++static grub_efi_net_interface_t * ++grub_efi_ip6_interface_match (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *ip_address) ++{ ++ grub_efi_ip6_config_interface_info_t *interface_info; ++ grub_efi_net_interface_t *inf; ++ int i; ++ grub_efi_ipv6_address_t *address = &ip_address->ip6; ++ ++ interface_info = efi_ip6_config_interface_info (dev->ip6_config); ++ if (!interface_info) ++ return NULL; ++ ++ for (i = 0; i < (int)interface_info->route_count ; i++) ++ { ++ grub_uint64_t u64_addr[2]; ++ grub_uint64_t u64_subnet[2]; ++ grub_uint64_t u64_mask[2]; ++ ++ grub_efi_ip6_route_table_t *route_table = interface_info->route_table + i; ++ ++ /* SKIP Default GATEWAY */ ++ if (route_table->prefix_length == 0) ++ continue; ++ ++ u64_addr[0] = grub_get_unaligned64 (address); ++ u64_addr[1] = grub_get_unaligned64 (address + 4); ++ u64_subnet[0] = grub_get_unaligned64 (route_table->destination.addr); ++ u64_subnet[1] = grub_get_unaligned64 (route_table->destination.addr + 8); ++ u64_mask[0] = (route_table->prefix_length <= 64) ? ++ 0xffffffffffffffffULL << (64 - route_table->prefix_length) : ++ 0xffffffffffffffffULL; ++ u64_mask[1] = (route_table->prefix_length <= 64) ? ++ 0 : ++ 0xffffffffffffffffULL << (128 - route_table->prefix_length); ++ ++ if (((u64_addr[0] & u64_mask[0]) == u64_subnet[0]) ++ && ((u64_addr[1] & u64_mask[1]) == u64_subnet[1])) ++ { ++ for (inf = dev->net_interfaces; inf; inf = inf->next) ++ if (inf->prefer_ip6) ++ { ++ grub_free (interface_info); ++ return inf; ++ } ++ } ++ } ++ ++ grub_free (interface_info); ++ return NULL; ++} ++ ++static int ++grub_efi_ip6_interface_set_manual_address (struct grub_efi_net_device *dev, ++ grub_efi_net_ip_manual_address_t *net_ip, ++ int with_subnet) ++{ ++ grub_efi_status_t status; ++ grub_efi_ip6_config_manual_address_t *address = &net_ip->ip6; ++ ++ if (!with_subnet) ++ { ++ grub_efi_ip6_config_manual_address_t *manual_address = ++ efi_ip6_config_manual_address (dev->ip6_config); ++ ++ if (manual_address) ++ { ++ address->prefix_length = manual_address->prefix_length; ++ grub_free (manual_address); ++ } ++ else ++ { ++ /* XXX: */ ++ address->prefix_length = 64; ++ } ++ } ++ ++ status = efi_call_4 (dev->ip6_config->set_data, dev->ip6_config, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS, ++ sizeof(*address), address); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ return 0; ++ ++ return 1; ++} ++ ++static int ++grub_efi_ip6_interface_set_gateway (struct grub_efi_net_device *dev, ++ grub_efi_net_ip_address_t *address) ++{ ++ grub_efi_status_t status; ++ ++ status = efi_call_4 (dev->ip6_config->set_data, dev->ip6_config, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_GATEWAY, ++ sizeof (address->ip6), &address->ip6); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ return 0; ++ return 1; ++} ++ ++static int ++grub_efi_ip6_interface_set_dns (struct grub_efi_net_device *dev, ++ grub_efi_net_ip_address_t *address) ++{ ++ ++ grub_efi_status_t status; ++ ++ status = efi_call_4 (dev->ip6_config->set_data, dev->ip6_config, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER, ++ sizeof (address->ip6), &address->ip6); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ return 0; ++ return 1; ++} ++ ++grub_efi_net_ip_config_t *efi_net_ip6_config = &(grub_efi_net_ip_config_t) ++ { ++ .get_hw_address = grub_efi_ip6_interface_hw_address, ++ .get_address = grub_efi_ip6_interface_address, ++ .get_route_table = grub_efi_ip6_interface_route_table, ++ .best_interface = grub_efi_ip6_interface_match, ++ .set_address = grub_efi_ip6_interface_set_manual_address, ++ .set_gateway = grub_efi_ip6_interface_set_gateway, ++ .set_dns = grub_efi_ip6_interface_set_dns ++ }; +diff --git a/grub-core/net/efi/net.c b/grub-core/net/efi/net.c +new file mode 100644 +index 00000000000..9e0078ac1c6 +--- /dev/null ++++ b/grub-core/net/efi/net.c +@@ -0,0 +1,1428 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++#define GRUB_EFI_IP6_PREFIX_LENGTH 64 ++ ++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_efi_guid_t http_service_binding_guid = GRUB_EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID; ++static grub_efi_guid_t http_guid = GRUB_EFI_HTTP_PROTOCOL_GUID; ++static grub_efi_guid_t pxe_io_guid = GRUB_EFI_PXE_GUID; ++static grub_efi_guid_t dhcp4_service_binding_guid = GRUB_EFI_DHCP4_SERVICE_BINDING_PROTOCOL_GUID; ++static grub_efi_guid_t dhcp4_guid = GRUB_EFI_DHCP4_PROTOCOL_GUID; ++static grub_efi_guid_t dhcp6_service_binding_guid = GRUB_EFI_DHCP6_SERVICE_BINDING_PROTOCOL_GUID; ++static grub_efi_guid_t dhcp6_guid = GRUB_EFI_DHCP6_PROTOCOL_GUID; ++ ++struct grub_efi_net_device *net_devices; ++ ++static char *default_server; ++static grub_efi_net_interface_t *net_interface; ++static grub_efi_net_interface_t *net_default_interface; ++ ++#define efi_net_interface_configure(inf) inf->io->configure (inf->dev, inf->prefer_ip6) ++#define efi_net_interface_open(inf, file, name) inf->io->open (inf->dev, inf->prefer_ip6, file, name, inf->io_type) ++#define efi_net_interface_read(inf, file, buf, sz) inf->io->read (inf->dev, inf->prefer_ip6, file, buf, sz) ++#define efi_net_interface_close(inf, file) inf->io->close (inf->dev, inf->prefer_ip6, file) ++#define efi_net_interface(m,...) efi_net_interface_ ## m (net_interface, ## __VA_ARGS__) ++ ++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 int ++url_parse_fields (const char *url, char **proto, char **host, char **path) ++{ ++ const char *p, *ps; ++ grub_size_t l; ++ ++ *proto = *host = *path = NULL; ++ ps = p = url; ++ ++ while ((p = grub_strchr (p, ':'))) ++ { ++ if (grub_strlen (p) < sizeof ("://") - 1) ++ break; ++ if (grub_memcmp (p, "://", sizeof ("://") - 1) == 0) ++ { ++ l = p - ps; ++ *proto = grub_malloc (l + 1); ++ if (!*proto) ++ { ++ grub_print_error (); ++ return 0; ++ } ++ ++ grub_memcpy (*proto, ps, l); ++ (*proto)[l] = '\0'; ++ p += sizeof ("://") - 1; ++ break; ++ } ++ ++p; ++ } ++ ++ if (!*proto) ++ { ++ grub_dprintf ("bootp", "url: %s is not valid, protocol not found\n", url); ++ return 0; ++ } ++ ++ ps = p; ++ p = grub_strchr (p, '/'); ++ ++ if (!p) ++ { ++ grub_dprintf ("bootp", "url: %s is not valid, host/path not found\n", url); ++ grub_free (*proto); ++ *proto = NULL; ++ return 0; ++ } ++ ++ l = p - ps; ++ ++ if (l > 2 && ps[0] == '[' && ps[l - 1] == ']') ++ { ++ *host = grub_malloc (l - 1); ++ if (!*host) ++ { ++ grub_print_error (); ++ grub_free (*proto); ++ *proto = NULL; ++ return 0; ++ } ++ grub_memcpy (*host, ps + 1, l - 2); ++ (*host)[l - 2] = 0; ++ } ++ else ++ { ++ *host = grub_malloc (l + 1); ++ if (!*host) ++ { ++ grub_print_error (); ++ grub_free (*proto); ++ *proto = NULL; ++ return 0; ++ } ++ grub_memcpy (*host, ps, l); ++ (*host)[l] = 0; ++ } ++ ++ *path = grub_strdup (p); ++ if (!*path) ++ { ++ grub_print_error (); ++ grub_free (*host); ++ grub_free (*proto); ++ *host = NULL; ++ *proto = NULL; ++ return 0; ++ } ++ return 1; ++} ++ ++static void ++url_get_boot_location (const char *url, char **device, char **path, int is_default) ++{ ++ char *protocol, *server, *file; ++ char *slash; ++ ++ if (!url_parse_fields (url, &protocol, &server, &file)) ++ return; ++ ++ if ((slash = grub_strrchr (file, '/'))) ++ *slash = 0; ++ else ++ *file = 0; ++ ++ *device = grub_xasprintf ("%s,%s", protocol, server); ++ *path = grub_strdup(file); ++ ++ if (is_default) ++ default_server = server; ++ else ++ grub_free (server); ++ ++ grub_free (protocol); ++ grub_free (file); ++} ++ ++static void ++pxe_get_boot_location (const struct grub_net_bootp_packet *bp, ++ char **device, ++ char **path, ++ int is_default) ++{ ++ char *server = grub_xasprintf ("%d.%d.%d.%d", ++ ((grub_uint8_t *) &bp->server_ip)[0], ++ ((grub_uint8_t *) &bp->server_ip)[1], ++ ((grub_uint8_t *) &bp->server_ip)[2], ++ ((grub_uint8_t *) &bp->server_ip)[3]); ++ ++ *device = grub_xasprintf ("tftp,%s", server); ++ ++ *path = grub_strndup (bp->boot_file, sizeof (bp->boot_file)); ++ ++ if (*path) ++ { ++ char *slash; ++ slash = grub_strrchr (*path, '/'); ++ if (slash) ++ *slash = 0; ++ else ++ **path = 0; ++ } ++ ++ if (is_default) ++ default_server = server; ++ else ++ grub_free (server); ++} ++ ++static void ++pxe_get_boot_location_v6 (const struct grub_net_dhcp6_packet *dp, ++ grub_size_t dhcp_size, ++ char **device, ++ char **path) ++{ ++ ++ struct grub_net_dhcp6_option *dhcp_opt; ++ grub_size_t dhcp_remain_size; ++ *device = *path = 0; ++ ++ if (dhcp_size < sizeof (*dp)) ++ { ++ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("DHCPv6 packet size too small")); ++ return; ++ } ++ ++ dhcp_remain_size = dhcp_size - sizeof (*dp); ++ dhcp_opt = (struct grub_net_dhcp6_option *)dp->dhcp_options; ++ ++ while (dhcp_remain_size) ++ { ++ grub_uint16_t code = grub_be_to_cpu16 (dhcp_opt->code); ++ grub_uint16_t len = grub_be_to_cpu16 (dhcp_opt->len); ++ grub_uint16_t option_size = sizeof (*dhcp_opt) + len; ++ ++ if (dhcp_remain_size < option_size || code == 0) ++ break; ++ ++ if (code == GRUB_NET_DHCP6_OPTION_BOOTFILE_URL) ++ { ++ char *url = grub_malloc (len + 1); ++ ++ grub_memcpy (url, dhcp_opt->data, len); ++ url[len] = 0; ++ ++ url_get_boot_location ((const char *)url, device, path, 1); ++ grub_free (url); ++ break; ++ } ++ ++ dhcp_remain_size -= option_size; ++ dhcp_opt = (struct grub_net_dhcp6_option *)((grub_uint8_t *)dhcp_opt + option_size); ++ } ++} ++ ++static grub_efi_net_interface_t * ++grub_efi_net_config_from_device_path (grub_efi_device_path_t *dp, ++ struct grub_efi_net_device *netdev, ++ char **device, ++ char **path) ++{ ++ grub_efi_net_interface_t *inf = NULL; ++ ++ while (1) ++ { ++ grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp); ++ grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp); ++ grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp); ++ ++ if (type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE) ++ { ++ if (subtype == GRUB_EFI_URI_DEVICE_PATH_SUBTYPE) ++ { ++ grub_efi_uri_device_path_t *uri_dp; ++ uri_dp = (grub_efi_uri_device_path_t *) dp; ++ /* Beware that uri_dp->uri may not be null terminated */ ++ url_get_boot_location ((const char *)uri_dp->uri, device, path, 1); ++ } ++ else if (subtype == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE) ++ { ++ grub_efi_net_ip_manual_address_t net_ip; ++ grub_efi_ipv4_device_path_t *ipv4 = (grub_efi_ipv4_device_path_t *) dp; ++ ++ if (inf) ++ continue; ++ grub_memcpy (net_ip.ip4.address, ipv4->local_ip_address, sizeof (net_ip.ip4.address)); ++ grub_memcpy (net_ip.ip4.subnet_mask, ipv4->subnet_mask, sizeof (net_ip.ip4.subnet_mask)); ++ net_ip.is_ip6 = 0; ++ inf = grub_efi_net_create_interface (netdev, ++ netdev->card_name, ++ &net_ip, ++ 1); ++ } ++ else if (subtype == GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE) ++ { ++ grub_efi_net_ip_manual_address_t net_ip; ++ grub_efi_ipv6_device_path_t *ipv6 = (grub_efi_ipv6_device_path_t *) dp; ++ ++ if (inf) ++ continue; ++ grub_memcpy (net_ip.ip6.address, ipv6->local_ip_address, sizeof (net_ip.ip6.address)); ++ net_ip.ip6.prefix_length = GRUB_EFI_IP6_PREFIX_LENGTH; ++ net_ip.ip6.is_anycast = 0; ++ net_ip.is_ip6 = 1; ++ inf = grub_efi_net_create_interface (netdev, ++ netdev->card_name, ++ &net_ip, ++ 1); ++ } ++ } ++ ++ if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp)) ++ break; ++ dp = (grub_efi_device_path_t *) ((char *) dp + len); ++ } ++ ++ return inf; ++} ++ ++static grub_efi_net_interface_t * ++grub_efi_net_config_from_handle (grub_efi_handle_t *hnd, ++ struct grub_efi_net_device *netdev, ++ char **device, ++ char **path) ++{ ++ grub_efi_pxe_t *pxe = NULL; ++ ++ if (hnd == netdev->ip4_pxe_handle) ++ pxe = netdev->ip4_pxe; ++ else if (hnd == netdev->ip6_pxe_handle) ++ pxe = netdev->ip6_pxe; ++ ++ if (!pxe) ++ return (grub_efi_net_config_from_device_path ( ++ grub_efi_get_device_path (hnd), ++ netdev, ++ device, ++ path)); ++ ++ if (pxe->mode->using_ipv6) ++ { ++ grub_efi_net_ip_manual_address_t net_ip; ++ ++ pxe_get_boot_location_v6 ( ++ (const struct grub_net_dhcp6_packet *) &pxe->mode->dhcp_ack, ++ sizeof (pxe->mode->dhcp_ack), ++ device, ++ path); ++ ++ grub_memcpy (net_ip.ip6.address, pxe->mode->station_ip.v6, sizeof(net_ip.ip6.address)); ++ net_ip.ip6.prefix_length = GRUB_EFI_IP6_PREFIX_LENGTH; ++ net_ip.ip6.is_anycast = 0; ++ net_ip.is_ip6 = 1; ++ return (grub_efi_net_create_interface (netdev, ++ netdev->card_name, ++ &net_ip, ++ 1)); ++ } ++ else ++ { ++ grub_efi_net_ip_manual_address_t net_ip; ++ ++ pxe_get_boot_location ( ++ (const struct grub_net_bootp_packet *) &pxe->mode->dhcp_ack, ++ device, ++ path, ++ 1); ++ ++ grub_memcpy (net_ip.ip4.address, pxe->mode->station_ip.v4, sizeof (net_ip.ip4.address)); ++ grub_memcpy (net_ip.ip4.subnet_mask, pxe->mode->subnet_mask.v4, sizeof (net_ip.ip4.subnet_mask)); ++ net_ip.is_ip6 = 0; ++ return (grub_efi_net_create_interface (netdev, ++ netdev->card_name, ++ &net_ip, ++ 1)); ++ } ++} ++ ++static const char * ++grub_efi_net_var_get_address (struct grub_env_var *var, ++ const char *val __attribute__ ((unused))) ++{ ++ struct grub_efi_net_device *dev; ++ ++ for (dev = net_devices; dev; dev = dev->next) ++ { ++ grub_efi_net_interface_t *inf; ++ ++ for (inf = dev->net_interfaces; inf; inf = inf->next) ++ { ++ char *var_name; ++ ++ var_name = grub_xasprintf ("net_%s_ip", inf->name); ++ if (grub_strcmp (var_name, var->name) == 0) ++ return efi_net_interface_get_address (inf); ++ grub_free (var_name); ++ var_name = grub_xasprintf ("net_%s_mac", inf->name); ++ if (grub_strcmp (var_name, var->name) == 0) ++ return efi_net_interface_get_hw_address (inf); ++ grub_free (var_name); ++ } ++ } ++ ++ return NULL; ++} ++ ++static char * ++grub_efi_net_var_set_interface (struct grub_env_var *var __attribute__ ((unused)), ++ const char *val) ++{ ++ struct grub_efi_net_device *dev; ++ grub_efi_net_interface_t *inf; ++ ++ for (dev = net_devices; dev; dev = dev->next) ++ for (inf = dev->net_interfaces; inf; inf = inf->next) ++ if (grub_strcmp (inf->name, val) == 0) ++ { ++ net_default_interface = inf; ++ return grub_strdup (val); ++ } ++ ++ return NULL; ++} ++ ++static char * ++grub_efi_net_var_set_server (struct grub_env_var *var __attribute__ ((unused)), ++ const char *val) ++{ ++ grub_free (default_server); ++ default_server = grub_strdup (val); ++ return grub_strdup (val); ++} ++ ++static const char * ++grub_efi_net_var_get_server (struct grub_env_var *var __attribute__ ((unused)), ++ const char *val __attribute__ ((unused))) ++{ ++ return default_server ? : ""; ++} ++ ++static const char * ++grub_efi_net_var_get_ip (struct grub_env_var *var __attribute__ ((unused)), ++ const char *val __attribute__ ((unused))) ++{ ++ const char *intf = grub_env_get ("net_default_interface"); ++ const char *ret = NULL; ++ if (intf) ++ { ++ char *buf = grub_xasprintf ("net_%s_ip", intf); ++ if (buf) ++ ret = grub_env_get (buf); ++ grub_free (buf); ++ } ++ return ret; ++} ++ ++static const char * ++grub_efi_net_var_get_mac (struct grub_env_var *var __attribute__ ((unused)), ++ const char *val __attribute__ ((unused))) ++{ ++ const char *intf = grub_env_get ("net_default_interface"); ++ const char *ret = NULL; ++ if (intf) ++ { ++ char *buf = grub_xasprintf ("net_%s_mac", intf); ++ if (buf) ++ ret = grub_env_get (buf); ++ grub_free (buf); ++ } ++ return ret; ++} ++ ++static void ++grub_efi_net_export_interface_vars (void) ++{ ++ struct grub_efi_net_device *dev; ++ ++ for (dev = net_devices; dev; dev = dev->next) ++ { ++ grub_efi_net_interface_t *inf; ++ ++ for (inf = dev->net_interfaces; inf; inf = inf->next) ++ { ++ char *var; ++ ++ var = grub_xasprintf ("net_%s_ip", inf->name); ++ grub_register_variable_hook (var, grub_efi_net_var_get_address, 0); ++ grub_env_export (var); ++ grub_free (var); ++ var = grub_xasprintf ("net_%s_mac", inf->name); ++ grub_register_variable_hook (var, grub_efi_net_var_get_address, 0); ++ grub_env_export (var); ++ grub_free (var); ++ } ++ } ++} ++ ++static void ++grub_efi_net_unset_interface_vars (void) ++{ ++ struct grub_efi_net_device *dev; ++ ++ for (dev = net_devices; dev; dev = dev->next) ++ { ++ grub_efi_net_interface_t *inf; ++ ++ for (inf = dev->net_interfaces; inf; inf = inf->next) ++ { ++ char *var; ++ ++ var = grub_xasprintf ("net_%s_ip", inf->name); ++ grub_register_variable_hook (var, 0, 0); ++ grub_env_unset (var); ++ grub_free (var); ++ var = grub_xasprintf ("net_%s_mac", inf->name); ++ grub_register_variable_hook (var, 0, 0); ++ grub_env_unset (var); ++ grub_free (var); ++ } ++ } ++} ++ ++grub_efi_net_interface_t * ++grub_efi_net_create_interface (struct grub_efi_net_device *dev, ++ const char *interface_name, ++ grub_efi_net_ip_manual_address_t *net_ip, ++ int has_subnet) ++{ ++ grub_efi_net_interface_t *inf; ++ ++ for (inf = dev->net_interfaces; inf; inf = inf->next) ++ { ++ if (inf->prefer_ip6 == net_ip->is_ip6) ++ break; ++ } ++ ++ if (!inf) ++ { ++ inf = grub_malloc (sizeof(*inf)); ++ inf->name = grub_strdup (interface_name); ++ inf->prefer_ip6 = net_ip->is_ip6; ++ inf->dev = dev; ++ inf->next = dev->net_interfaces; ++ inf->ip_config = (net_ip->is_ip6) ? efi_net_ip6_config : efi_net_ip4_config ; ++ dev->net_interfaces = inf; ++ } ++ else ++ { ++ grub_free (inf->name); ++ inf->name = grub_strdup (interface_name); ++ } ++ ++ if (!efi_net_interface_set_address (inf, net_ip, has_subnet)) ++ { ++ grub_error (GRUB_ERR_BUG, N_("Set Address Failed")); ++ return NULL; ++ } ++ ++ return inf; ++} ++ ++static void ++grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, ++ char **path) ++{ ++ grub_efi_handle_t config_hnd; ++ ++ struct grub_efi_net_device *netdev; ++ grub_efi_net_interface_t *inf; ++ ++ config_hnd = grub_efi_locate_device_path (&ip4_config_guid, grub_efi_get_device_path (hnd), NULL); ++ ++ if (!config_hnd) ++ return; ++ ++ for (netdev = net_devices; netdev; netdev = netdev->next) ++ if (netdev->handle == config_hnd) ++ break; ++ ++ if (!netdev) ++ return; ++ ++ if (!(inf = grub_efi_net_config_from_handle (hnd, netdev, device, path))) ++ return; ++ ++ grub_env_set ("net_default_interface", inf->name); ++ grub_efi_net_export_interface_vars (); ++} ++ ++static grub_err_t ++grub_efi_netfs_dir (grub_device_t device, const char *path __attribute__ ((unused)), ++ grub_fs_dir_hook_t hook __attribute__ ((unused)), ++ void *hook_data __attribute__ ((unused))) ++{ ++ if (!device->net) ++ return grub_error (GRUB_ERR_BUG, "invalid net device"); ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_efi_netfs_open (struct grub_file *file_out __attribute__ ((unused)), ++ const char *name __attribute__ ((unused))) ++{ ++ struct grub_file *file, *bufio; ++ ++ file = grub_malloc (sizeof (*file)); ++ if (!file) ++ return grub_errno; ++ ++ grub_memcpy (file, file_out, sizeof (struct grub_file)); ++ file->device->net->name = grub_strdup (name); ++ ++ if (!file->device->net->name) ++ { ++ grub_free (file); ++ return grub_errno; ++ } ++ ++ efi_net_interface(open, file, name); ++ grub_print_error (); ++ ++ bufio = grub_bufio_open (file, 32768); ++ if (!bufio) ++ { ++ grub_free (file->device->net->name); ++ grub_free (file); ++ return grub_errno; ++ } ++ grub_memcpy (file_out, bufio, sizeof (struct grub_file)); ++ grub_free (bufio); ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_ssize_t ++grub_efihttp_chunk_read (grub_file_t file, char *buf, ++ grub_size_t len, grub_size_t chunk_size) ++{ ++ char *chunk = grub_malloc (chunk_size); ++ grub_size_t sum = 0; ++ ++ while (len) ++ { ++ grub_ssize_t rd; ++ grub_size_t sz = (len > chunk_size) ? chunk_size : len; ++ ++ rd = efi_net_interface (read, file, chunk, sz); ++ ++ if (rd <= 0) ++ return rd; ++ ++ if (buf) ++ { ++ grub_memcpy (buf, chunk, rd); ++ buf += rd; ++ } ++ sum += rd; ++ len -= rd; ++ } ++ ++ grub_free (chunk); ++ return sum; ++} ++ ++static grub_ssize_t ++grub_efi_netfs_read (grub_file_t file __attribute__ ((unused)), ++ char *buf __attribute__ ((unused)), grub_size_t len __attribute__ ((unused))) ++{ ++ if (file->offset > file->device->net->offset) ++ { ++ grub_efihttp_chunk_read (file, NULL, file->offset - file->device->net->offset, 10240); ++ } ++ else if (file->offset < file->device->net->offset) ++ { ++ efi_net_interface (close, file); ++ efi_net_interface (open, file, file->device->net->name); ++ if (file->offset) ++ grub_efihttp_chunk_read (file, NULL, file->offset, 10240); ++ } ++ ++ return efi_net_interface (read, file, buf, len); ++} ++ ++static grub_err_t ++grub_efi_netfs_close (grub_file_t file) ++{ ++ efi_net_interface (close, file); ++ return GRUB_ERR_NONE; ++} ++ ++static grub_efi_handle_t ++grub_efi_service_binding (grub_efi_handle_t dev, grub_efi_guid_t *service_binding_guid) ++{ ++ grub_efi_service_binding_t *service; ++ grub_efi_status_t status; ++ grub_efi_handle_t child_dev = NULL; ++ ++ service = grub_efi_open_protocol (dev, service_binding_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); ++ if (!service) ++ { ++ grub_error (GRUB_ERR_IO, N_("couldn't open efi service binding protocol")); ++ return NULL; ++ } ++ ++ status = efi_call_2 (service->create_child, service, &child_dev); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_error (GRUB_ERR_IO, N_("Failed to create child device of http service %x"), status); ++ return NULL; ++ } ++ ++ return child_dev; ++} ++ ++static grub_err_t ++grub_efi_net_parse_address (const char *address, ++ grub_efi_ip4_config2_manual_address_t *ip4, ++ grub_efi_ip6_config_manual_address_t *ip6, ++ int *is_ip6, ++ int *has_cidr) ++{ ++ const char *rest; ++ ++ if (grub_efi_string_to_ip4_address (address, &ip4->address, &rest)) ++ { ++ *is_ip6 = 0; ++ if (*rest == '/') ++ { ++ grub_uint32_t subnet_mask_size; ++ ++ subnet_mask_size = grub_strtoul (rest + 1, (char **) &rest, 0); ++ ++ if (!grub_errno && subnet_mask_size <= 32 && *rest == 0) ++ { ++ grub_uint32_t subnet_mask; ++ ++ subnet_mask = grub_cpu_to_be32 ((0xffffffffU << (32 - subnet_mask_size))); ++ grub_memcpy (ip4->subnet_mask, &subnet_mask, sizeof (ip4->subnet_mask)); ++ if (has_cidr) ++ *has_cidr = 1; ++ return GRUB_ERR_NONE; ++ } ++ } ++ else if (*rest == 0) ++ { ++ grub_uint32_t subnet_mask = 0xffffffffU; ++ grub_memcpy (ip4->subnet_mask, &subnet_mask, sizeof (ip4->subnet_mask)); ++ if (has_cidr) ++ *has_cidr = 0; ++ return GRUB_ERR_NONE; ++ } ++ } ++ else if (grub_efi_string_to_ip6_address (address, &ip6->address, &rest)) ++ { ++ *is_ip6 = 1; ++ if (*rest == '/') ++ { ++ grub_efi_uint8_t prefix_length; ++ ++ prefix_length = grub_strtoul (rest + 1, (char **) &rest, 0); ++ if (!grub_errno && prefix_length <= 128 && *rest == 0) ++ { ++ ip6->prefix_length = prefix_length; ++ ip6->is_anycast = 0; ++ if (has_cidr) ++ *has_cidr = 1; ++ return GRUB_ERR_NONE; ++ } ++ } ++ else if (*rest == 0) ++ { ++ ip6->prefix_length = 128; ++ ip6->is_anycast = 0; ++ if (has_cidr) ++ *has_cidr = 0; ++ return GRUB_ERR_NONE; ++ } ++ } ++ ++ return grub_error (GRUB_ERR_NET_BAD_ADDRESS, ++ N_("unrecognised network address `%s'"), ++ address); ++} ++ ++static grub_efi_net_interface_t * ++match_route (const char *server) ++{ ++ grub_err_t err; ++ grub_efi_ip4_config2_manual_address_t ip4; ++ grub_efi_ip6_config_manual_address_t ip6; ++ grub_efi_net_interface_t *inf; ++ int is_ip6 = 0; ++ ++ err = grub_efi_net_parse_address (server, &ip4, &ip6, &is_ip6, 0); ++ ++ if (err) ++ { ++ grub_print_error (); ++ return NULL; ++ } ++ ++ if (is_ip6) ++ { ++ struct grub_efi_net_device *dev; ++ grub_efi_net_ip_address_t addr; ++ ++ grub_memcpy (addr.ip6, ip6.address, sizeof(ip6.address)); ++ ++ for (dev = net_devices; dev; dev = dev->next) ++ if ((inf = efi_net_ip6_config->best_interface (dev, &addr))) ++ return inf; ++ } ++ else ++ { ++ struct grub_efi_net_device *dev; ++ grub_efi_net_ip_address_t addr; ++ ++ grub_memcpy (addr.ip4, ip4.address, sizeof(ip4.address)); ++ ++ for (dev = net_devices; dev; dev = dev->next) ++ if ((inf = efi_net_ip4_config->best_interface (dev, &addr))) ++ return inf; ++ } ++ ++ return 0; ++} ++ ++static void ++grub_efi_net_add_pxebc_to_cards (void) ++{ ++ grub_efi_uintn_t num_handles; ++ grub_efi_handle_t *handles; ++ grub_efi_handle_t *handle; ++ ++ handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &pxe_io_guid, ++ 0, &num_handles); ++ if (!handles) ++ return; ++ ++ for (handle = handles; num_handles--; handle++) ++ { ++ grub_efi_device_path_t *dp, *ddp, *ldp; ++ grub_efi_pxe_t *pxe; ++ struct grub_efi_net_device *d; ++ int is_ip6 = 0; ++ ++ dp = grub_efi_get_device_path (*handle); ++ if (!dp) ++ continue; ++ ++ ddp = grub_efi_duplicate_device_path (dp); ++ ldp = grub_efi_find_last_device_path (ddp); ++ ++ if (ldp->type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE ++ && ldp->subtype == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE) ++ { ++ ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; ++ ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; ++ ldp->length = sizeof (*ldp); ++ } ++ else if (ldp->type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE ++ && ldp->subtype == GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE) ++ { ++ is_ip6 = 1; ++ ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; ++ ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; ++ ldp->length = sizeof (*ldp); ++ } ++ ++ for (d = net_devices; d; d = d->next) ++ if (grub_efi_compare_device_paths (ddp, grub_efi_get_device_path (d->handle)) == 0) ++ break; ++ ++ if (!d) ++ { ++ grub_free (ddp); ++ continue; ++ } ++ ++ pxe = grub_efi_open_protocol (*handle, &pxe_io_guid, ++ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); ++ ++ if (!pxe) ++ { ++ grub_free (ddp); ++ continue; ++ } ++ ++ if (is_ip6) ++ { ++ d->ip6_pxe_handle = *handle; ++ d->ip6_pxe = pxe; ++ } ++ else ++ { ++ d->ip4_pxe_handle = *handle; ++ d->ip4_pxe = pxe; ++ } ++ ++ grub_free (ddp); ++ } ++ ++ grub_free (handles); ++} ++ ++static void ++set_ip_policy_to_static (void) ++{ ++ struct grub_efi_net_device *dev; ++ ++ for (dev = net_devices; dev; dev = dev->next) ++ { ++ grub_efi_ip4_config2_policy_t ip4_policy = GRUB_EFI_IP4_CONFIG2_POLICY_STATIC; ++ ++ if (efi_call_4 (dev->ip4_config->set_data, dev->ip4_config, ++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_POLICY, ++ sizeof (ip4_policy), &ip4_policy) != GRUB_EFI_SUCCESS) ++ grub_dprintf ("efinetfs", "could not set GRUB_EFI_IP4_CONFIG2_POLICY_STATIC on dev `%s'", dev->card_name); ++ ++ if (dev->ip6_config) ++ { ++ grub_efi_ip6_config_policy_t ip6_policy = GRUB_EFI_IP6_CONFIG_POLICY_MANUAL; ++ ++ if (efi_call_4 (dev->ip6_config->set_data, dev->ip6_config, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_POLICY, ++ sizeof (ip6_policy), &ip6_policy) != GRUB_EFI_SUCCESS) ++ grub_dprintf ("efinetfs", "could not set GRUB_EFI_IP6_CONFIG_POLICY_MANUAL on dev `%s'", dev->card_name); ++ } ++ } ++} ++ ++/* FIXME: Do not fail if the card did not support any of the protocol (Eg http) */ ++static void ++grub_efi_net_find_cards (void) ++{ ++ grub_efi_uintn_t num_handles; ++ grub_efi_handle_t *handles; ++ grub_efi_handle_t *handle; ++ int id; ++ ++ handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &ip4_config_guid, ++ 0, &num_handles); ++ if (!handles) ++ return; ++ ++ for (id = 0, handle = handles; num_handles--; handle++, id++) ++ { ++ grub_efi_device_path_t *dp; ++ grub_efi_ip4_config2_protocol_t *ip4_config; ++ grub_efi_ip6_config_protocol_t *ip6_config; ++ grub_efi_handle_t http_handle; ++ grub_efi_http_t *http; ++ grub_efi_handle_t dhcp4_handle; ++ grub_efi_dhcp4_protocol_t *dhcp4; ++ grub_efi_handle_t dhcp6_handle; ++ grub_efi_dhcp6_protocol_t *dhcp6; ++ ++ struct grub_efi_net_device *d; ++ ++ dp = grub_efi_get_device_path (*handle); ++ if (!dp) ++ continue; ++ ++ ip4_config = grub_efi_open_protocol (*handle, &ip4_config_guid, ++ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); ++ if (!ip4_config) ++ continue; ++ ++ ip6_config = grub_efi_open_protocol (*handle, &ip6_config_guid, ++ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); ++ ++ http_handle = grub_efi_service_binding (*handle, &http_service_binding_guid); ++ grub_errno = GRUB_ERR_NONE; ++ http = (http_handle) ++ ? grub_efi_open_protocol (http_handle, &http_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL) ++ : NULL; ++ ++ dhcp4_handle = grub_efi_service_binding (*handle, &dhcp4_service_binding_guid); ++ grub_errno = GRUB_ERR_NONE; ++ dhcp4 = (dhcp4_handle) ++ ? grub_efi_open_protocol (dhcp4_handle, &dhcp4_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL) ++ : NULL; ++ ++ ++ dhcp6_handle = grub_efi_service_binding (*handle, &dhcp6_service_binding_guid); ++ grub_errno = GRUB_ERR_NONE; ++ dhcp6 = (dhcp6_handle) ++ ? grub_efi_open_protocol (dhcp6_handle, &dhcp6_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL) ++ : NULL; ++ ++ d = grub_malloc (sizeof (*d)); ++ if (!d) ++ { ++ grub_free (handles); ++ while (net_devices) ++ { ++ d = net_devices->next; ++ grub_free (net_devices); ++ net_devices = d; ++ } ++ return; ++ } ++ d->handle = *handle; ++ d->ip4_config = ip4_config; ++ d->ip6_config = ip6_config; ++ d->http_handle = http_handle; ++ d->http = http; ++ d->dhcp4_handle = dhcp4_handle; ++ d->dhcp4 = dhcp4; ++ d->dhcp6_handle = dhcp6_handle; ++ d->dhcp6 = dhcp6; ++ d->next = net_devices; ++ d->card_name = grub_xasprintf ("efinet%d", id); ++ d->net_interfaces = NULL; ++ net_devices = d; ++ } ++ ++ grub_efi_net_add_pxebc_to_cards (); ++ grub_free (handles); ++ set_ip_policy_to_static (); ++} ++ ++static void ++listroutes_ip4 (struct grub_efi_net_device *netdev) ++{ ++ char **routes; ++ ++ routes = NULL; ++ ++ if ((routes = efi_net_ip4_config->get_route_table (netdev))) ++ { ++ char **r; ++ ++ for (r = routes; *r; ++r) ++ grub_printf ("%s\n", *r); ++ } ++ ++ if (routes) ++ { ++ char **r; ++ ++ for (r = routes; *r; ++r) ++ grub_free (*r); ++ grub_free (routes); ++ } ++} ++ ++static void ++listroutes_ip6 (struct grub_efi_net_device *netdev) ++{ ++ char **routes; ++ ++ routes = NULL; ++ ++ if ((routes = efi_net_ip6_config->get_route_table (netdev))) ++ { ++ char **r; ++ ++ for (r = routes; *r; ++r) ++ grub_printf ("%s\n", *r); ++ } ++ ++ if (routes) ++ { ++ char **r; ++ ++ for (r = routes; *r; ++r) ++ grub_free (*r); ++ grub_free (routes); ++ } ++} ++ ++static grub_err_t ++grub_cmd_efi_listroutes (struct grub_command *cmd __attribute__ ((unused)), ++ int argc __attribute__ ((unused)), ++ char **args __attribute__ ((unused))) ++{ ++ struct grub_efi_net_device *netdev; ++ ++ for (netdev = net_devices; netdev; netdev = netdev->next) ++ { ++ listroutes_ip4 (netdev); ++ listroutes_ip6 (netdev); ++ } ++ ++ return GRUB_ERR_NONE; ++} ++static grub_err_t ++grub_cmd_efi_listcards (struct grub_command *cmd __attribute__ ((unused)), ++ int argc __attribute__ ((unused)), ++ char **args __attribute__ ((unused))) ++{ ++ struct grub_efi_net_device *dev; ++ ++ for (dev = net_devices; dev; dev = dev->next) ++ { ++ char *hw_addr; ++ ++ hw_addr = efi_net_ip4_config->get_hw_address (dev); ++ ++ if (hw_addr) ++ { ++ grub_printf ("%s %s\n", dev->card_name, hw_addr); ++ grub_free (hw_addr); ++ } ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_cmd_efi_listaddrs (struct grub_command *cmd __attribute__ ((unused)), ++ int argc __attribute__ ((unused)), ++ char **args __attribute__ ((unused))) ++{ ++ struct grub_efi_net_device *dev; ++ grub_efi_net_interface_t *inf; ++ ++ for (dev = net_devices; dev; dev = dev->next) ++ for (inf = dev->net_interfaces; inf; inf = inf->next) ++ { ++ char *hw_addr = NULL; ++ char *addr = NULL; ++ ++ if ((hw_addr = efi_net_interface_get_hw_address (inf)) ++ && (addr = efi_net_interface_get_address (inf))) ++ grub_printf ("%s %s %s\n", inf->name, hw_addr, addr); ++ ++ if (hw_addr) ++ grub_free (hw_addr); ++ if (addr) ++ grub_free (addr); ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ ++/* FIXME: support MAC specifying. */ ++static grub_err_t ++grub_cmd_efi_addaddr (struct grub_command *cmd __attribute__ ((unused)), ++ int argc, char **args) ++{ ++ struct grub_efi_net_device *dev; ++ grub_err_t err; ++ grub_efi_ip4_config2_manual_address_t ip4; ++ grub_efi_ip6_config_manual_address_t ip6; ++ grub_efi_net_ip_manual_address_t net_ip; ++ int is_ip6 = 0; ++ int cidr = 0; ++ ++ if (argc != 3) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("three arguments expected")); ++ ++ for (dev = net_devices; dev; dev = dev->next) ++ { ++ if (grub_strcmp (dev->card_name, args[1]) == 0) ++ break; ++ } ++ ++ if (!dev) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("card not found")); ++ ++ err = grub_efi_net_parse_address (args[2], &ip4, &ip6, &is_ip6, &cidr); ++ ++ if (err) ++ return err; ++ ++ net_ip.is_ip6 = is_ip6; ++ if (is_ip6) ++ grub_memcpy (&net_ip.ip6, &ip6, sizeof(net_ip.ip6)); ++ else ++ grub_memcpy (&net_ip.ip4, &ip4, sizeof(net_ip.ip4)); ++ ++ if (!grub_efi_net_create_interface (dev, ++ args[0], ++ &net_ip, ++ cidr)) ++ return grub_errno; ++ ++ return GRUB_ERR_NONE; ++} ++ ++static struct grub_fs grub_efi_netfs; ++ ++static grub_net_t ++grub_net_open_real (const char *name __attribute__ ((unused))) ++{ ++ grub_size_t protnamelen; ++ const char *protname, *server; ++ grub_net_t ret; ++ ++ net_interface = NULL; ++ ++ if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0) ++ { ++ protname = "tftp"; ++ protnamelen = sizeof ("tftp") - 1; ++ server = name + sizeof ("pxe:") - 1; ++ } ++ else if (grub_strcmp (name, "pxe") == 0) ++ { ++ protname = "tftp"; ++ protnamelen = sizeof ("tftp") - 1; ++ server = default_server; ++ } ++ else ++ { ++ const char *comma; ++ ++ comma = grub_strchr (name, ','); ++ if (comma) ++ { ++ protnamelen = comma - name; ++ server = comma + 1; ++ protname = name; ++ } ++ else ++ { ++ protnamelen = grub_strlen (name); ++ server = default_server; ++ protname = name; ++ } ++ } ++ ++ if (!server) ++ { ++ grub_error (GRUB_ERR_NET_BAD_ADDRESS, ++ N_("no server is specified")); ++ return NULL; ++ } ++ ++ /*FIXME: Use DNS translate name to address */ ++ net_interface = match_route (server); ++ ++ /*XXX: should we check device with default gateway ? */ ++ if (!net_interface && !(net_interface = net_default_interface)) ++ { ++ grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("disk `%s' no route found"), ++ name); ++ return NULL; ++ } ++ ++ if ((protnamelen == (sizeof ("https") - 1) ++ && grub_memcmp ("https", protname, protnamelen) == 0)) ++ { ++ net_interface->io = &io_http; ++ net_interface->io_type = 1; ++ } ++ else if ((protnamelen == (sizeof ("http") - 1) ++ && grub_memcmp ("http", protname, protnamelen) == 0)) ++ { ++ net_interface->io = &io_http; ++ net_interface->io_type = 0; ++ } ++ else if (protnamelen == (sizeof ("tftp") - 1) ++ && grub_memcmp ("tftp", protname, protnamelen) == 0) ++ { ++ net_interface->io = &io_pxe; ++ net_interface->io_type = 0; ++ } ++ else ++ { ++ grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("disk `%s' not found"), ++ name); ++ return NULL; ++ } ++ ++ /*XXX: Should we try to avoid doing excess "reconfigure" here ??? */ ++ efi_net_interface (configure); ++ ++ ret = grub_zalloc (sizeof (*ret)); ++ if (!ret) ++ return NULL; ++ ++ ret->server = grub_strdup (server); ++ if (!ret->server) ++ { ++ grub_free (ret); ++ return NULL; ++ } ++ ++ ret->fs = &grub_efi_netfs; ++ return ret; ++} ++#if 0 ++static grub_command_t cmd_efi_lsaddr; ++static grub_command_t cmd_efi_lscards; ++static grub_command_t cmd_efi_lsroutes; ++static grub_command_t cmd_efi_addaddr; ++#endif ++ ++static struct grub_fs grub_efi_netfs = ++ { ++ .name = "efi netfs", ++ .dir = grub_efi_netfs_dir, ++ .open = grub_efi_netfs_open, ++ .read = grub_efi_netfs_read, ++ .close = grub_efi_netfs_close, ++ .label = NULL, ++ .uuid = NULL, ++ .mtime = NULL, ++ }; ++ ++int ++grub_efi_net_boot_from_https (void) ++{ ++ grub_efi_loaded_image_t *image = NULL; ++ grub_efi_device_path_t *dp; ++ ++ image = grub_efi_get_loaded_image (grub_efi_image_handle); ++ if (!image) ++ return 0; ++ ++ dp = grub_efi_get_device_path (image->device_handle); ++ ++ while (1) ++ { ++ grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp); ++ grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp); ++ grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp); ++ ++ if ((type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE) ++ && (subtype == GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)) ++ { ++ grub_efi_uri_device_path_t *uri_dp = (grub_efi_uri_device_path_t *) dp; ++ return (grub_strncmp ((const char*)uri_dp->uri, "https://", sizeof ("https://") - 1) == 0) ? 1 : 0; ++ } ++ ++ if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp)) ++ break; ++ dp = (grub_efi_device_path_t *) ((char *) dp + len); ++ } ++ ++ return 0; ++} ++ ++int ++grub_efi_net_boot_from_opa (void) ++{ ++ grub_efi_loaded_image_t *image = NULL; ++ grub_efi_device_path_t *dp; ++ ++ image = grub_efi_get_loaded_image (grub_efi_image_handle); ++ if (!image) ++ return 0; ++ ++ dp = grub_efi_get_device_path (image->device_handle); ++ ++ while (1) ++ { ++ grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp); ++ grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp); ++ grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp); ++ ++ if ((type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE) ++ && (subtype == GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE)) ++ { ++ grub_efi_mac_address_device_path_t *mac_dp = (grub_efi_mac_address_device_path_t *)dp; ++ return (mac_dp->if_type == 0xC7) ? 1 : 0; ++ } ++ ++ if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp)) ++ break; ++ dp = (grub_efi_device_path_t *) ((char *) dp + len); ++ } ++ ++ return 0; ++} ++ ++static char * ++grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)), ++ const char *val __attribute__ ((unused))) ++{ ++ return NULL; ++} ++ ++grub_command_func_t grub_efi_net_list_routes = grub_cmd_efi_listroutes; ++grub_command_func_t grub_efi_net_list_cards = grub_cmd_efi_listcards; ++grub_command_func_t grub_efi_net_list_addrs = grub_cmd_efi_listaddrs; ++grub_command_func_t grub_efi_net_add_addr = grub_cmd_efi_addaddr; ++ ++int ++grub_efi_net_fs_init () ++{ ++ grub_efi_net_find_cards (); ++ grub_efi_net_config = grub_efi_net_config_real; ++ grub_net_open = grub_net_open_real; ++ grub_register_variable_hook ("net_default_server", grub_efi_net_var_get_server, ++ grub_efi_net_var_set_server); ++ grub_env_export ("net_default_server"); ++ grub_register_variable_hook ("pxe_default_server", grub_efi_net_var_get_server, ++ grub_efi_net_var_set_server); ++ grub_env_export ("pxe_default_server"); ++ grub_register_variable_hook ("net_default_interface", 0, ++ grub_efi_net_var_set_interface); ++ grub_env_export ("net_default_interface"); ++ grub_register_variable_hook ("net_default_ip", grub_efi_net_var_get_ip, ++ 0); ++ grub_env_export ("net_default_ip"); ++ grub_register_variable_hook ("net_default_mac", grub_efi_net_var_get_mac, ++ 0); ++ grub_env_export ("net_default_mac"); ++ ++ grub_env_set ("grub_netfs_type", "efi"); ++ grub_register_variable_hook ("grub_netfs_type", 0, grub_env_write_readonly); ++ grub_env_export ("grub_netfs_type"); ++ ++ return 1; ++} ++ ++void ++grub_efi_net_fs_fini (void) ++{ ++ grub_env_unset ("grub_netfs_type"); ++ grub_efi_net_unset_interface_vars (); ++ grub_register_variable_hook ("net_default_server", 0, 0); ++ grub_env_unset ("net_default_server"); ++ grub_register_variable_hook ("net_default_interface", 0, 0); ++ grub_env_unset ("net_default_interface"); ++ grub_register_variable_hook ("pxe_default_server", 0, 0); ++ grub_env_unset ("pxe_default_server"); ++ grub_register_variable_hook ("net_default_ip", 0, 0); ++ grub_env_unset ("net_default_ip"); ++ grub_register_variable_hook ("net_default_mac", 0, 0); ++ grub_env_unset ("net_default_mac"); ++ grub_efi_net_config = NULL; ++ grub_net_open = NULL; ++ grub_fs_unregister (&grub_efi_netfs); ++} +diff --git a/grub-core/net/efi/pxe.c b/grub-core/net/efi/pxe.c +new file mode 100644 +index 00000000000..531949cba5c +--- /dev/null ++++ b/grub-core/net/efi/pxe.c +@@ -0,0 +1,424 @@ ++ ++#include ++#include ++#include ++#include ++#include ++ ++static grub_efi_ip6_config_manual_address_t * ++efi_ip6_config_manual_address (grub_efi_ip6_config_protocol_t *ip6_config) ++{ ++ grub_efi_uintn_t sz; ++ grub_efi_status_t status; ++ grub_efi_ip6_config_manual_address_t *manual_address; ++ ++ sz = sizeof (*manual_address); ++ manual_address = grub_malloc (sz); ++ if (!manual_address) ++ return NULL; ++ ++ status = efi_call_4 (ip6_config->get_data, ip6_config, ++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS, ++ &sz, manual_address); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_free (manual_address); ++ return NULL; ++ } ++ ++ return manual_address; ++} ++ ++static grub_efi_ip4_config2_manual_address_t * ++efi_ip4_config_manual_address (grub_efi_ip4_config2_protocol_t *ip4_config) ++{ ++ grub_efi_uintn_t sz; ++ grub_efi_status_t status; ++ grub_efi_ip4_config2_manual_address_t *manual_address; ++ ++ sz = sizeof (*manual_address); ++ manual_address = grub_malloc (sz); ++ if (!manual_address) ++ return NULL; ++ ++ status = efi_call_4 (ip4_config->get_data, ip4_config, ++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS, ++ &sz, manual_address); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_free (manual_address); ++ return NULL; ++ } ++ ++ return manual_address; ++} ++ ++static void ++pxe_configure (struct grub_efi_net_device *dev, int prefer_ip6) ++{ ++ grub_efi_pxe_t *pxe = (prefer_ip6) ? dev->ip6_pxe : dev->ip4_pxe; ++ ++ grub_efi_pxe_mode_t *mode = pxe->mode; ++ ++ if (!mode->started) ++ { ++ grub_efi_status_t status; ++ status = efi_call_2 (pxe->start, pxe, prefer_ip6); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ grub_printf ("Couldn't start PXE\n"); ++ } ++ ++#if 0 ++ grub_printf ("PXE STARTED: %u\n", mode->started); ++ grub_printf ("PXE USING IPV6: %u\n", mode->using_ipv6); ++#endif ++ ++ if (mode->using_ipv6) ++ { ++ grub_efi_ip6_config_manual_address_t *manual_address; ++ manual_address = efi_ip6_config_manual_address (dev->ip6_config); ++ ++ if (manual_address && ++ grub_memcmp (manual_address->address, mode->station_ip.v6, sizeof (manual_address->address)) != 0) ++ { ++ grub_efi_status_t status; ++ grub_efi_pxe_ip_address_t station_ip; ++ ++ grub_memcpy (station_ip.v6.addr, manual_address->address, sizeof (station_ip.v6.addr)); ++ status = efi_call_3 (pxe->set_station_ip, pxe, &station_ip, NULL); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ grub_printf ("Couldn't set station ip\n"); ++ ++ grub_free (manual_address); ++ } ++ } ++ else ++ { ++ grub_efi_ip4_config2_manual_address_t *manual_address; ++ manual_address = efi_ip4_config_manual_address (dev->ip4_config); ++ ++ if (manual_address && ++ grub_memcmp (manual_address->address, mode->station_ip.v4, sizeof (manual_address->address)) != 0) ++ { ++ grub_efi_status_t status; ++ grub_efi_pxe_ip_address_t station_ip; ++ grub_efi_pxe_ip_address_t subnet_mask; ++ ++ grub_memcpy (station_ip.v4.addr, manual_address->address, sizeof (station_ip.v4.addr)); ++ grub_memcpy (subnet_mask.v4.addr, manual_address->subnet_mask, sizeof (subnet_mask.v4.addr)); ++ ++ status = efi_call_3 (pxe->set_station_ip, pxe, &station_ip, &subnet_mask); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ grub_printf ("Couldn't set station ip\n"); ++ ++ grub_free (manual_address); ++ } ++ } ++ ++#if 0 ++ if (mode->using_ipv6) ++ { ++ grub_printf ("PXE STATION IP: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", ++ mode->station_ip.v6.addr[0], ++ mode->station_ip.v6.addr[1], ++ mode->station_ip.v6.addr[2], ++ mode->station_ip.v6.addr[3], ++ mode->station_ip.v6.addr[4], ++ mode->station_ip.v6.addr[5], ++ mode->station_ip.v6.addr[6], ++ mode->station_ip.v6.addr[7], ++ mode->station_ip.v6.addr[8], ++ mode->station_ip.v6.addr[9], ++ mode->station_ip.v6.addr[10], ++ mode->station_ip.v6.addr[11], ++ mode->station_ip.v6.addr[12], ++ mode->station_ip.v6.addr[13], ++ mode->station_ip.v6.addr[14], ++ mode->station_ip.v6.addr[15]); ++ } ++ else ++ { ++ grub_printf ("PXE STATION IP: %d.%d.%d.%d\n", ++ mode->station_ip.v4.addr[0], ++ mode->station_ip.v4.addr[1], ++ mode->station_ip.v4.addr[2], ++ mode->station_ip.v4.addr[3]); ++ grub_printf ("PXE SUBNET MASK: %d.%d.%d.%d\n", ++ mode->subnet_mask.v4.addr[0], ++ mode->subnet_mask.v4.addr[1], ++ mode->subnet_mask.v4.addr[2], ++ mode->subnet_mask.v4.addr[3]); ++ } ++#endif ++ ++ /* TODO: Set The Station IP to the IP2 Config */ ++} ++ ++static int ++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; ++ if (ptr[0] == ':') ++ ptr++; ++ ++ for (word = 0; word < 8; word++) ++ { ++ unsigned long t; ++ if (*ptr == ':') ++ { ++ quaddot = word; ++ word--; ++ ptr++; ++ continue; ++ } ++ t = grub_strtoul (ptr, (char **) &ptr, 16); ++ if (grub_errno) ++ { ++ grub_errno = GRUB_ERR_NONE; ++ break; ++ } ++ if (t & ~0xffff) ++ return 0; ++ newip[word] = grub_cpu_to_be16 (t); ++ if (*ptr != ':') ++ break; ++ ptr++; ++ } ++ if (quaddot == -1 && word < 7) ++ return 0; ++ if (quaddot != -1) ++ { ++ grub_memmove (&newip[quaddot + 7 - word], &newip[quaddot], ++ (word - quaddot + 1) * sizeof (newip[0])); ++ 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; ++} ++ ++static grub_err_t ++pxe_open (struct grub_efi_net_device *dev, ++ int prefer_ip6, ++ grub_file_t file, ++ const char *filename, ++ int type __attribute__((unused))) ++{ ++ int i; ++ char *p; ++ grub_efi_status_t status; ++ grub_efi_pxe_ip_address_t server_ip; ++ grub_efi_uint64_t file_size = 0; ++ grub_efi_pxe_t *pxe = (prefer_ip6) ? dev->ip6_pxe : dev->ip4_pxe; ++ ++ if (pxe->mode->using_ipv6) ++ { ++ const char *rest; ++ grub_uint64_t ip6[2]; ++ if (parse_ip6 (file->device->net->server, ip6, &rest) && *rest == 0) ++ grub_memcpy (server_ip.v6.addr, ip6, sizeof (server_ip.v6.addr)); ++ /* TODO: ERROR Handling Here */ ++#if 0 ++ grub_printf ("PXE SERVER IP: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", ++ server_ip.v6.addr[0], ++ server_ip.v6.addr[1], ++ server_ip.v6.addr[2], ++ server_ip.v6.addr[3], ++ server_ip.v6.addr[4], ++ server_ip.v6.addr[5], ++ server_ip.v6.addr[6], ++ server_ip.v6.addr[7], ++ server_ip.v6.addr[8], ++ server_ip.v6.addr[9], ++ server_ip.v6.addr[10], ++ server_ip.v6.addr[11], ++ server_ip.v6.addr[12], ++ server_ip.v6.addr[13], ++ server_ip.v6.addr[14], ++ server_ip.v6.addr[15]); ++#endif ++ } ++ else ++ { ++ for (i = 0, p = file->device->net->server; i < 4; ++i, ++p) ++ server_ip.v4.addr[i] = grub_strtoul (p, &p, 10); ++ } ++ ++ status = efi_call_10 (pxe->mtftp, ++ pxe, ++ GRUB_EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE, ++ NULL, ++ 0, ++ &file_size, ++ NULL, ++ &server_ip, ++ (grub_efi_char8_t *)filename, ++ NULL, ++ 0); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ return grub_error (GRUB_ERR_IO, "Couldn't get file size"); ++ ++ file->size = (grub_off_t)file_size; ++ file->not_easily_seekable = 0; ++ file->data = 0; ++ file->device->net->offset = 0; ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++pxe_close (struct grub_efi_net_device *dev __attribute__((unused)), ++ int prefer_ip6 __attribute__((unused)), ++ grub_file_t file __attribute__((unused))) ++{ ++ file->offset = 0; ++ file->size = 0; ++ file->device->net->offset = 0; ++ ++ if (file->data) ++ { ++ grub_free (file->data); ++ file->data = NULL; ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_ssize_t ++pxe_read (struct grub_efi_net_device *dev, ++ int prefer_ip6, ++ grub_file_t file, ++ char *buf, ++ grub_size_t len) ++{ ++ int i; ++ char *p; ++ grub_efi_status_t status; ++ grub_efi_pxe_t *pxe = (prefer_ip6) ? dev->ip6_pxe : dev->ip4_pxe; ++ grub_efi_uint64_t bufsz = len; ++ grub_efi_pxe_ip_address_t server_ip; ++ char *buf2 = NULL; ++ ++ if (file->data) ++ { ++ /* TODO: RANGE Check for offset and file size */ ++ grub_memcpy (buf, (char*)file->data + file->device->net->offset, len); ++ file->device->net->offset += len; ++ return len; ++ } ++ ++ if (file->device->net->offset) ++ { ++ grub_error (GRUB_ERR_BUG, "No Offet Read Possible"); ++ grub_print_error (); ++ return 0; ++ } ++ ++ if (pxe->mode->using_ipv6) ++ { ++ const char *rest; ++ grub_uint64_t ip6[2]; ++ if (parse_ip6 (file->device->net->server, ip6, &rest) && *rest == 0) ++ grub_memcpy (server_ip.v6.addr, ip6, sizeof (server_ip.v6.addr)); ++ /* TODO: ERROR Handling Here */ ++ } ++ else ++ { ++ for (i = 0, p = file->device->net->server; i < 4; ++i, ++p) ++ server_ip.v4.addr[i] = grub_strtoul (p, &p, 10); ++ } ++ ++ status = efi_call_10 (pxe->mtftp, ++ pxe, ++ GRUB_EFI_PXE_BASE_CODE_TFTP_READ_FILE, ++ buf, ++ 0, ++ &bufsz, ++ NULL, ++ &server_ip, ++ (grub_efi_char8_t *)file->device->net->name, ++ NULL, ++ 0); ++ ++ if (bufsz != file->size) ++ { ++ grub_error (GRUB_ERR_BUG, "Short read should not happen here"); ++ grub_print_error (); ++ return 0; ++ } ++ ++ if (status == GRUB_EFI_BUFFER_TOO_SMALL) ++ { ++ ++ buf2 = grub_malloc (bufsz); ++ ++ if (!buf2) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, "ERROR OUT OF MEMORY"); ++ grub_print_error (); ++ return 0; ++ } ++ ++ status = efi_call_10 (pxe->mtftp, ++ pxe, ++ GRUB_EFI_PXE_BASE_CODE_TFTP_READ_FILE, ++ buf2, ++ 0, ++ &bufsz, ++ NULL, ++ &server_ip, ++ (grub_efi_char8_t *)file->device->net->name, ++ NULL, ++ 0); ++ } ++ ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ if (buf2) ++ grub_free (buf2); ++ ++ grub_error (GRUB_ERR_IO, "Failed to Read File"); ++ grub_print_error (); ++ return 0; ++ } ++ ++ if (buf2) ++ grub_memcpy (buf, buf2, len); ++ ++ file->device->net->offset = len; ++ ++ if (buf2) ++ file->data = buf2; ++ ++ return len; ++} ++ ++struct grub_efi_net_io io_pxe = ++ { ++ .configure = pxe_configure, ++ .open = pxe_open, ++ .read = pxe_read, ++ .close = pxe_close ++ }; ++ +diff --git a/grub-core/net/net.c b/grub-core/net/net.c +index a6566bdb00a..cfe4cb62760 100644 +--- a/grub-core/net/net.c ++++ b/grub-core/net/net.c +@@ -32,6 +32,9 @@ + #include + #include + #include ++#ifdef GRUB_MACHINE_EFI ++#include ++#endif + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -1978,8 +1981,49 @@ static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; + static grub_command_t cmd_lsroutes, cmd_lscards; + static grub_command_t cmd_lsaddr, cmd_slaac; + ++#ifdef GRUB_MACHINE_EFI ++ ++static enum { ++ INIT_MODE_NONE, ++ INIT_MODE_GRUB, ++ INIT_MODE_EFI ++} init_mode; ++ ++static grub_command_t cmd_bootp, cmd_bootp6; ++ ++#endif ++ + GRUB_MOD_INIT(net) + { ++#ifdef GRUB_MACHINE_EFI ++ if (grub_net_open) ++ return; ++ ++ if ((grub_efi_net_boot_from_https () || grub_efi_net_boot_from_opa ()) ++ && grub_efi_net_fs_init ()) ++ { ++ cmd_lsroutes = grub_register_command ("net_ls_routes", grub_efi_net_list_routes, ++ "", N_("list network routes")); ++ cmd_lscards = grub_register_command ("net_ls_cards", grub_efi_net_list_cards, ++ "", N_("list network cards")); ++ cmd_lsaddr = grub_register_command ("net_ls_addr", grub_efi_net_list_addrs, ++ "", N_("list network addresses")); ++ cmd_addaddr = grub_register_command ("net_add_addr", grub_efi_net_add_addr, ++ /* TRANSLATORS: HWADDRESS stands for ++ "hardware address". */ ++ N_("SHORTNAME CARD ADDRESS [HWADDRESS]"), ++ N_("Add a network address.")); ++ cmd_bootp = grub_register_command ("net_bootp", grub_efi_net_bootp, ++ N_("[CARD]"), ++ N_("perform a bootp autoconfiguration")); ++ cmd_bootp6 = grub_register_command ("net_bootp6", grub_efi_net_bootp6, ++ N_("[CARD]"), ++ N_("perform a bootp autoconfiguration")); ++ init_mode = INIT_MODE_EFI; ++ return; ++ } ++#endif ++ + grub_register_variable_hook ("net_default_server", defserver_get_env, + defserver_set_env); + grub_env_export ("net_default_server"); +@@ -2027,10 +2071,37 @@ GRUB_MOD_INIT(net) + grub_net_restore_hw, + GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK); + grub_net_poll_cards_idle = grub_net_poll_cards_idle_real; ++ ++#ifdef GRUB_MACHINE_EFI ++ grub_env_set ("grub_netfs_type", "grub"); ++ grub_register_variable_hook ("grub_netfs_type", 0, grub_env_write_readonly); ++ grub_env_export ("grub_netfs_type"); ++ init_mode = INIT_MODE_GRUB; ++#endif ++ + } + + GRUB_MOD_FINI(net) + { ++ ++#ifdef GRUB_MACHINE_EFI ++ if (init_mode == INIT_MODE_NONE) ++ return; ++ ++ if (init_mode == INIT_MODE_EFI) ++ { ++ grub_unregister_command (cmd_lsroutes); ++ grub_unregister_command (cmd_lscards); ++ grub_unregister_command (cmd_lsaddr); ++ grub_unregister_command (cmd_addaddr); ++ grub_unregister_command (cmd_bootp); ++ grub_unregister_command (cmd_bootp6); ++ grub_efi_net_fs_fini (); ++ init_mode = INIT_MODE_NONE; ++ return; ++ } ++#endif ++ + grub_register_variable_hook ("net_default_server", 0, 0); + grub_register_variable_hook ("pxe_default_server", 0, 0); + +@@ -2049,4 +2120,7 @@ GRUB_MOD_FINI(net) + grub_net_fini_hw (0); + grub_loader_unregister_preboot_hook (fini_hnd); + grub_net_poll_cards_idle = grub_net_poll_cards_idle_real; ++#ifdef GRUB_MACHINE_EFI ++ init_mode = INIT_MODE_NONE; ++#endif + } +diff --git a/util/grub-mknetdir.c b/util/grub-mknetdir.c +index 8366a1121a1..8997336e901 100644 +--- a/util/grub-mknetdir.c ++++ b/util/grub-mknetdir.c +@@ -32,13 +32,15 @@ + + static char *rootdir = NULL, *subdir = NULL; + static char *debug_image = NULL; ++static char efi_netfs = 0; + + enum + { + OPTION_NET_DIRECTORY = 0x301, + OPTION_SUBDIR, + OPTION_DEBUG, +- OPTION_DEBUG_IMAGE ++ OPTION_DEBUG_IMAGE, ++ OPTION_DEBUG_EFI_NETFS + }; + + static struct argp_option options[] = { +@@ -49,6 +51,7 @@ static struct argp_option options[] = { + 0, N_("relative subdirectory on network server"), 2}, + {"debug", OPTION_DEBUG, 0, OPTION_HIDDEN, 0, 2}, + {"debug-image", OPTION_DEBUG_IMAGE, N_("STRING"), OPTION_HIDDEN, 0, 2}, ++ {"debug-efi-netfs", OPTION_DEBUG_EFI_NETFS, 0, OPTION_HIDDEN, 0, 2}, + {0, 0, 0, 0, 0, 0} + }; + +@@ -67,6 +70,9 @@ argp_parser (int key, char *arg, struct argp_state *state) + free (subdir); + subdir = xstrdup (arg); + return 0; ++ case OPTION_DEBUG_EFI_NETFS: ++ efi_netfs = 1; ++ return 0; + /* This is an undocumented feature... */ + case OPTION_DEBUG: + verbosity++; +@@ -82,7 +88,6 @@ argp_parser (int key, char *arg, struct argp_state *state) + } + } + +- + struct argp argp = { + options, argp_parser, NULL, + "\v"N_("Prepares GRUB network boot images at net_directory/subdir " +@@ -92,7 +97,7 @@ struct argp argp = { + + static char *base; + +-static const struct ++static struct + { + const char *mkimage_target; + const char *netmodule; +@@ -153,6 +158,7 @@ process_input_dir (const char *input_dir, enum grub_install_plat platform) + grub_install_push_module (targets[platform].netmodule); + + output = grub_util_path_concat_ext (2, grubdir, "core", targets[platform].ext); ++ + grub_install_make_image_wrap (input_dir, prefix, output, + 0, load_cfg, + targets[platform].mkimage_target, 0); +@@ -189,7 +195,16 @@ main (int argc, char *argv[]) + + grub_install_mkdir_p (base); + +- grub_install_push_module ("tftp"); ++ if (!efi_netfs) ++ { ++ grub_install_push_module ("tftp"); ++ grub_install_push_module ("http"); ++ } ++ else ++ { ++ targets[GRUB_INSTALL_PLATFORM_I386_EFI].netmodule = "efi_netfs"; ++ targets[GRUB_INSTALL_PLATFORM_X86_64_EFI].netmodule = "efi_netfs"; ++ } + + if (!grub_install_source_directory) + { +diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h +index 852daddfb0f..fbd1c4b529d 100644 +--- a/include/grub/efi/api.h ++++ b/include/grub/efi/api.h +@@ -549,6 +549,23 @@ typedef union + + typedef grub_efi_uint64_t grub_efi_physical_address_t; + typedef grub_efi_uint64_t grub_efi_virtual_address_t; ++typedef struct { ++ grub_uint8_t addr[4]; ++} grub_efi_pxe_ipv4_address_t; ++ ++typedef struct { ++ grub_uint8_t addr[16]; ++} grub_efi_pxe_ipv6_address_t; ++ ++typedef struct { ++ grub_uint8_t addr[32]; ++} grub_efi_pxe_mac_address_t; ++ ++typedef union { ++ grub_uint32_t addr[4]; ++ grub_efi_pxe_ipv4_address_t v4; ++ grub_efi_pxe_ipv6_address_t v6; ++} grub_efi_pxe_ip_address_t; + + struct grub_efi_guid + { +@@ -812,6 +829,8 @@ struct grub_efi_ipv6_device_path + grub_efi_uint16_t remote_port; + grub_efi_uint16_t protocol; + grub_efi_uint8_t static_ip_address; ++ grub_efi_uint8_t prefix_length; ++ grub_efi_ipv6_address_t gateway_ip_address; + } GRUB_PACKED; + typedef struct grub_efi_ipv6_device_path grub_efi_ipv6_device_path_t; + +@@ -861,6 +880,15 @@ struct grub_efi_uri_device_path + } GRUB_PACKED; + typedef struct grub_efi_uri_device_path grub_efi_uri_device_path_t; + ++#define GRUB_EFI_DNS_DEVICE_PATH_SUBTYPE 31 ++struct grub_efi_dns_device_path ++{ ++ grub_efi_device_path_t header; ++ grub_efi_uint8_t is_ipv6; ++ grub_efi_pxe_ip_address_t dns_server_ip[0]; ++} GRUB_PACKED; ++typedef struct grub_efi_dns_device_path grub_efi_dns_device_path_t; ++ + #define GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE 10 + + /* Media Device Path. */ +@@ -943,6 +971,23 @@ struct grub_efi_bios_device_path + } GRUB_PACKED; + typedef struct grub_efi_bios_device_path grub_efi_bios_device_path_t; + ++/* Service Binding definitions */ ++struct grub_efi_service_binding; ++ ++typedef grub_efi_status_t ++(*grub_efi_service_binding_create_child) (struct grub_efi_service_binding *this, ++ grub_efi_handle_t *child_handle); ++ ++typedef grub_efi_status_t ++(*grub_efi_service_binding_destroy_child) (struct grub_efi_service_binding *this, ++ grub_efi_handle_t *child_handle); ++ ++typedef struct grub_efi_service_binding ++{ ++ grub_efi_service_binding_create_child create_child; ++ grub_efi_service_binding_destroy_child destroy_child; ++} grub_efi_service_binding_t; ++ + struct grub_efi_open_protocol_information_entry + { + grub_efi_handle_t agent_handle; +@@ -1492,23 +1537,27 @@ typedef struct grub_efi_pxe_tftp_error + grub_efi_char8_t error_string[127]; + } grub_efi_pxe_tftp_error_t; + +-typedef struct { +- grub_uint8_t addr[4]; +-} grub_efi_pxe_ipv4_address_t; ++typedef grub_efi_uint16_t grub_efi_pxe_base_code_udp_port_t; + +-typedef struct { +- grub_uint8_t addr[16]; +-} grub_efi_pxe_ipv6_address_t; ++typedef enum { ++ GRUB_EFI_PXE_BASE_CODE_TFTP_FIRST, ++ GRUB_EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE, ++ GRUB_EFI_PXE_BASE_CODE_TFTP_READ_FILE, ++ GRUB_EFI_PXE_BASE_CODE_TFTP_WRITE_FILE, ++ GRUB_EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY, ++ GRUB_EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE, ++ GRUB_EFI_PXE_BASE_CODE_MTFTP_READ_FILE, ++ GRUB_EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY, ++ GRUB_EFI_PXE_BASE_CODE_MTFTP_LAST ++} grub_efi_pxe_base_code_tftp_opcode_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; ++ grub_efi_ip_address_t mcast_ip; ++ grub_efi_pxe_base_code_udp_port_t c_port; ++ grub_efi_pxe_base_code_udp_port_t s_port; ++ grub_efi_uint16_t listen_timeout; ++ grub_efi_uint16_t transmit_timeout; ++} grub_efi_pxe_base_code_mtftp_info_t; + + #define GRUB_EFI_PXE_BASE_CODE_MAX_IPCNT 8 + typedef struct grub_efi_pxe_ip_filter +@@ -1575,17 +1624,31 @@ typedef struct grub_efi_pxe_mode + typedef struct grub_efi_pxe + { + grub_uint64_t rev; +- void (*start) (void); ++ grub_efi_status_t (*start) (struct grub_efi_pxe *this, grub_efi_boolean_t use_ipv6); + void (*stop) (void); +- void (*dhcp) (void); ++ grub_efi_status_t (*dhcp) (struct grub_efi_pxe *this, ++ grub_efi_boolean_t sort_offers); + void (*discover) (void); +- void (*mftp) (void); ++ grub_efi_status_t (*mtftp) (struct grub_efi_pxe *this, ++ grub_efi_pxe_base_code_tftp_opcode_t operation, ++ void *buffer_ptr, ++ grub_efi_boolean_t overwrite, ++ grub_efi_uint64_t *buffer_size, ++ grub_efi_uintn_t *block_size, ++ grub_efi_pxe_ip_address_t *server_ip, ++ //grub_efi_ip_address_t *server_ip, ++ grub_efi_char8_t *filename, ++ grub_efi_pxe_base_code_mtftp_info_t *info, ++ grub_efi_boolean_t dont_use_buffer); + void (*udpwrite) (void); + void (*udpread) (void); + void (*setipfilter) (void); + void (*arp) (void); + void (*setparams) (void); +- void (*setstationip) (void); ++ grub_efi_status_t (*set_station_ip) (struct grub_efi_pxe *this, ++ grub_efi_pxe_ip_address_t *new_station_ip, ++ grub_efi_pxe_ip_address_t *new_subnet_mask); ++ //void (*setstationip) (void); + void (*setpackets) (void); + struct grub_efi_pxe_mode *mode; + } grub_efi_pxe_t; +@@ -1827,6 +1890,44 @@ struct grub_efi_ip4_config2_protocol + }; + typedef struct grub_efi_ip4_config2_protocol grub_efi_ip4_config2_protocol_t; + ++struct grub_efi_ip4_route_table { ++ grub_efi_ipv4_address_t subnet_address; ++ grub_efi_ipv4_address_t subnet_mask; ++ grub_efi_ipv4_address_t gateway_address; ++}; ++ ++typedef struct grub_efi_ip4_route_table grub_efi_ip4_route_table_t; ++ ++#define GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE 32 ++ ++struct grub_efi_ip4_config2_interface_info { ++ grub_efi_char16_t name[GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE]; ++ grub_efi_uint8_t if_type; ++ grub_efi_uint32_t hw_address_size; ++ grub_efi_mac_address_t hw_address; ++ grub_efi_ipv4_address_t station_address; ++ grub_efi_ipv4_address_t subnet_mask; ++ grub_efi_uint32_t route_table_size; ++ grub_efi_ip4_route_table_t *route_table; ++}; ++ ++typedef struct grub_efi_ip4_config2_interface_info grub_efi_ip4_config2_interface_info_t; ++ ++enum grub_efi_ip4_config2_policy { ++ GRUB_EFI_IP4_CONFIG2_POLICY_STATIC, ++ GRUB_EFI_IP4_CONFIG2_POLICY_DHCP, ++ GRUB_EFI_IP4_CONFIG2_POLICY_MAX ++}; ++ ++typedef enum grub_efi_ip4_config2_policy grub_efi_ip4_config2_policy_t; ++ ++struct grub_efi_ip4_config2_manual_address { ++ grub_efi_ipv4_address_t address; ++ grub_efi_ipv4_address_t subnet_mask; ++}; ++ ++typedef struct grub_efi_ip4_config2_manual_address grub_efi_ip4_config2_manual_address_t; ++ + enum grub_efi_ip6_config_data_type { + GRUB_EFI_IP6_CONFIG_DATA_TYPE_INTERFACEINFO, + GRUB_EFI_IP6_CONFIG_DATA_TYPE_ALT_INTERFACEID, +@@ -1861,6 +1962,49 @@ struct grub_efi_ip6_config_protocol + }; + typedef struct grub_efi_ip6_config_protocol grub_efi_ip6_config_protocol_t; + ++enum grub_efi_ip6_config_policy { ++ GRUB_EFI_IP6_CONFIG_POLICY_MANUAL, ++ GRUB_EFI_IP6_CONFIG_POLICY_AUTOMATIC ++}; ++typedef enum grub_efi_ip6_config_policy grub_efi_ip6_config_policy_t; ++ ++struct grub_efi_ip6_address_info { ++ grub_efi_ipv6_address_t address; ++ grub_efi_uint8_t prefix_length; ++}; ++typedef struct grub_efi_ip6_address_info grub_efi_ip6_address_info_t; ++ ++struct grub_efi_ip6_route_table { ++ grub_efi_pxe_ipv6_address_t gateway; ++ grub_efi_pxe_ipv6_address_t destination; ++ grub_efi_uint8_t prefix_length; ++}; ++typedef struct grub_efi_ip6_route_table grub_efi_ip6_route_table_t; ++ ++struct grub_efi_ip6_config_interface_info { ++ grub_efi_char16_t name[32]; ++ grub_efi_uint8_t if_type; ++ grub_efi_uint32_t hw_address_size; ++ grub_efi_mac_address_t hw_address; ++ grub_efi_uint32_t address_info_count; ++ grub_efi_ip6_address_info_t *address_info; ++ grub_efi_uint32_t route_count; ++ grub_efi_ip6_route_table_t *route_table; ++}; ++typedef struct grub_efi_ip6_config_interface_info grub_efi_ip6_config_interface_info_t; ++ ++struct grub_efi_ip6_config_dup_addr_detect_transmits { ++ grub_efi_uint32_t dup_addr_detect_transmits; ++}; ++typedef struct grub_efi_ip6_config_dup_addr_detect_transmits grub_efi_ip6_config_dup_addr_detect_transmits_t; ++ ++struct grub_efi_ip6_config_manual_address { ++ grub_efi_ipv6_address_t address; ++ grub_efi_boolean_t is_anycast; ++ grub_efi_uint8_t prefix_length; ++}; ++typedef struct grub_efi_ip6_config_manual_address grub_efi_ip6_config_manual_address_t; ++ + #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \ + || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) + +diff --git a/include/grub/efi/dhcp.h b/include/grub/efi/dhcp.h +new file mode 100644 +index 00000000000..fdb88eb810e +--- /dev/null ++++ b/include/grub/efi/dhcp.h +@@ -0,0 +1,343 @@ ++#ifndef GRUB_EFI_DHCP_HEADER ++#define GRUB_EFI_DHCP_HEADER 1 ++ ++#define GRUB_EFI_DHCP4_SERVICE_BINDING_PROTOCOL_GUID \ ++ { 0x9d9a39d8, 0xbd42, 0x4a73, \ ++ { 0xa4, 0xd5, 0x8e, 0xe9, 0x4b, 0xe1, 0x13, 0x80 } \ ++ } ++ ++#define GRUB_EFI_DHCP4_PROTOCOL_GUID \ ++ { 0x8a219718, 0x4ef5, 0x4761, \ ++ { 0x91, 0xc8, 0xc0, 0xf0, 0x4b, 0xda, 0x9e, 0x56 } \ ++ } ++ ++#define GRUB_EFI_DHCP6_SERVICE_BINDING_PROTOCOL_GUID \ ++ { 0x9fb9a8a1, 0x2f4a, 0x43a6, \ ++ { 0x88, 0x9c, 0xd0, 0xf7, 0xb6, 0xc4 ,0x7a, 0xd5 } \ ++ } ++ ++#define GRUB_EFI_DHCP6_PROTOCOL_GUID \ ++ { 0x87c8bad7, 0x595, 0x4053, \ ++ { 0x82, 0x97, 0xde, 0xde, 0x39, 0x5f, 0x5d, 0x5b } \ ++ } ++ ++typedef struct grub_efi_dhcp4_protocol grub_efi_dhcp4_protocol_t; ++ ++enum grub_efi_dhcp4_state { ++ GRUB_EFI_DHCP4_STOPPED, ++ GRUB_EFI_DHCP4_INIT, ++ GRUB_EFI_DHCP4_SELECTING, ++ GRUB_EFI_DHCP4_REQUESTING, ++ GRUB_EFI_DHCP4_BOUND, ++ GRUB_EFI_DHCP4_RENEWING, ++ GRUB_EFI_DHCP4_REBINDING, ++ GRUB_EFI_DHCP4_INIT_REBOOT, ++ GRUB_EFI_DHCP4_REBOOTING ++}; ++ ++typedef enum grub_efi_dhcp4_state grub_efi_dhcp4_state_t; ++ ++struct grub_efi_dhcp4_header { ++ grub_efi_uint8_t op_code; ++ grub_efi_uint8_t hw_type; ++ grub_efi_uint8_t hw_addr_len; ++ grub_efi_uint8_t hops; ++ grub_efi_uint32_t xid; ++ grub_efi_uint16_t seconds; ++ grub_efi_uint16_t reserved; ++ grub_efi_ipv4_address_t client_addr; ++ grub_efi_ipv4_address_t your_addr; ++ grub_efi_ipv4_address_t server_addr; ++ grub_efi_ipv4_address_t gateway_addr; ++ grub_efi_uint8_t client_hw_addr[16]; ++ grub_efi_char8_t server_name[64]; ++ grub_efi_char8_t boot_file_name[128]; ++} GRUB_PACKED; ++ ++typedef struct grub_efi_dhcp4_header grub_efi_dhcp4_header_t; ++ ++struct grub_efi_dhcp4_packet { ++ grub_efi_uint32_t size; ++ grub_efi_uint32_t length; ++ struct { ++ grub_efi_dhcp4_header_t header; ++ grub_efi_uint32_t magik; ++ grub_efi_uint8_t option[1]; ++ } dhcp4; ++} GRUB_PACKED; ++ ++typedef struct grub_efi_dhcp4_packet grub_efi_dhcp4_packet_t; ++ ++struct grub_efi_dhcp4_listen_point { ++ grub_efi_ipv4_address_t listen_address; ++ grub_efi_ipv4_address_t subnet_mask; ++ grub_efi_uint16_t listen_port; ++}; ++ ++typedef struct grub_efi_dhcp4_listen_point grub_efi_dhcp4_listen_point_t; ++ ++struct grub_efi_dhcp4_transmit_receive_token { ++ grub_efi_status_t status; ++ grub_efi_event_t completion_event; ++ grub_efi_ipv4_address_t remote_address; ++ grub_efi_uint16_t remote_port; ++ grub_efi_ipv4_address_t gateway_address; ++ grub_efi_uint32_t listen_point_count; ++ grub_efi_dhcp4_listen_point_t *listen_points; ++ grub_efi_uint32_t timeout_value; ++ grub_efi_dhcp4_packet_t *packet; ++ grub_efi_uint32_t response_count; ++ grub_efi_dhcp4_packet_t *response_list; ++}; ++ ++typedef struct grub_efi_dhcp4_transmit_receive_token grub_efi_dhcp4_transmit_receive_token_t; ++ ++enum grub_efi_dhcp4_event { ++ GRUB_EFI_DHCP4_SEND_DISCOVER = 0X01, ++ GRUB_EFI_DHCP4_RCVD_OFFER, ++ GRUB_EFI_DHCP4_SELECT_OFFER, ++ GRUB_EFI_DHCP4_SEND_REQUEST, ++ GRUB_EFI_DHCP4_RCVD_ACK, ++ GRUB_EFI_DHCP4_RCVD_NAK, ++ GRUB_EFI_DHCP4_SEND_DECLINE, ++ GRUB_EFI_DHCP4_BOUND_COMPLETED, ++ GRUB_EFI_DHCP4_ENTER_RENEWING, ++ GRUB_EFI_DHCP4_ENTER_REBINDING, ++ GRUB_EFI_DHCP4_ADDRESS_LOST, ++ GRUB_EFI_DHCP4_FAIL ++}; ++ ++typedef enum grub_efi_dhcp4_event grub_efi_dhcp4_event_t; ++ ++struct grub_efi_dhcp4_packet_option { ++ grub_efi_uint8_t op_code; ++ grub_efi_uint8_t length; ++ grub_efi_uint8_t data[1]; ++} GRUB_PACKED; ++ ++typedef struct grub_efi_dhcp4_packet_option grub_efi_dhcp4_packet_option_t; ++ ++struct grub_efi_dhcp4_config_data { ++ grub_efi_uint32_t discover_try_count; ++ grub_efi_uint32_t *discover_timeout; ++ grub_efi_uint32_t request_try_count; ++ grub_efi_uint32_t *request_timeout; ++ grub_efi_ipv4_address_t client_address; ++ grub_efi_status_t (*dhcp4_callback) ( ++ grub_efi_dhcp4_protocol_t *this, ++ void *context, ++ grub_efi_dhcp4_state_t current_state, ++ grub_efi_dhcp4_event_t dhcp4_event, ++ grub_efi_dhcp4_packet_t *packet, ++ grub_efi_dhcp4_packet_t **new_packet ++ ); ++ void *callback_context; ++ grub_efi_uint32_t option_count; ++ grub_efi_dhcp4_packet_option_t **option_list; ++}; ++ ++typedef struct grub_efi_dhcp4_config_data grub_efi_dhcp4_config_data_t; ++ ++struct grub_efi_dhcp4_mode_data { ++ grub_efi_dhcp4_state_t state; ++ grub_efi_dhcp4_config_data_t config_data; ++ grub_efi_ipv4_address_t client_address; ++ grub_efi_mac_address_t client_mac_address; ++ grub_efi_ipv4_address_t server_address; ++ grub_efi_ipv4_address_t router_address; ++ grub_efi_ipv4_address_t subnet_mask; ++ grub_efi_uint32_t lease_time; ++ grub_efi_dhcp4_packet_t *reply_packet; ++}; ++ ++typedef struct grub_efi_dhcp4_mode_data grub_efi_dhcp4_mode_data_t; ++ ++struct grub_efi_dhcp4_protocol { ++ grub_efi_status_t (*get_mode_data) (grub_efi_dhcp4_protocol_t *this, ++ grub_efi_dhcp4_mode_data_t *dhcp4_mode_data); ++ grub_efi_status_t (*configure) (grub_efi_dhcp4_protocol_t *this, ++ grub_efi_dhcp4_config_data_t *dhcp4_cfg_data); ++ grub_efi_status_t (*start) (grub_efi_dhcp4_protocol_t *this, ++ grub_efi_event_t completion_event); ++ grub_efi_status_t (*renew_rebind) (grub_efi_dhcp4_protocol_t *this, ++ grub_efi_boolean_t rebind_request, ++ grub_efi_event_t completion_event); ++ grub_efi_status_t (*release) (grub_efi_dhcp4_protocol_t *this); ++ grub_efi_status_t (*stop) (grub_efi_dhcp4_protocol_t *this); ++ grub_efi_status_t (*build) (grub_efi_dhcp4_protocol_t *this, ++ grub_efi_dhcp4_packet_t *seed_packet, ++ grub_efi_uint32_t delete_count, ++ grub_efi_uint8_t *delete_list, ++ grub_efi_uint32_t append_count, ++ grub_efi_dhcp4_packet_option_t *append_list[], ++ grub_efi_dhcp4_packet_t **new_packet); ++ grub_efi_status_t (*transmit_receive) (grub_efi_dhcp4_protocol_t *this, ++ grub_efi_dhcp4_transmit_receive_token_t *token); ++ grub_efi_status_t (*parse) (grub_efi_dhcp4_protocol_t *this, ++ grub_efi_dhcp4_packet_t *packet, ++ grub_efi_uint32_t *option_count, ++ grub_efi_dhcp4_packet_option_t *packet_option_list[]); ++}; ++ ++typedef struct grub_efi_dhcp6_protocol grub_efi_dhcp6_protocol_t; ++ ++struct grub_efi_dhcp6_retransmission { ++ grub_efi_uint32_t irt; ++ grub_efi_uint32_t mrc; ++ grub_efi_uint32_t mrt; ++ grub_efi_uint32_t mrd; ++}; ++ ++typedef struct grub_efi_dhcp6_retransmission grub_efi_dhcp6_retransmission_t; ++ ++enum grub_efi_dhcp6_event { ++ GRUB_EFI_DHCP6_SEND_SOLICIT, ++ GRUB_EFI_DHCP6_RCVD_ADVERTISE, ++ GRUB_EFI_DHCP6_SELECT_ADVERTISE, ++ GRUB_EFI_DHCP6_SEND_REQUEST, ++ GRUB_EFI_DHCP6_RCVD_REPLY, ++ GRUB_EFI_DHCP6_RCVD_RECONFIGURE, ++ GRUB_EFI_DHCP6_SEND_DECLINE, ++ GRUB_EFI_DHCP6_SEND_CONFIRM, ++ GRUB_EFI_DHCP6_SEND_RELEASE, ++ GRUB_EFI_DHCP6_SEND_RENEW, ++ GRUB_EFI_DHCP6_SEND_REBIND ++}; ++ ++typedef enum grub_efi_dhcp6_event grub_efi_dhcp6_event_t; ++ ++struct grub_efi_dhcp6_packet_option { ++ grub_efi_uint16_t op_code; ++ grub_efi_uint16_t op_len; ++ grub_efi_uint8_t data[1]; ++} GRUB_PACKED; ++ ++typedef struct grub_efi_dhcp6_packet_option grub_efi_dhcp6_packet_option_t; ++ ++struct grub_efi_dhcp6_header { ++ grub_efi_uint32_t transaction_id:24; ++ grub_efi_uint32_t message_type:8; ++} GRUB_PACKED; ++ ++typedef struct grub_efi_dhcp6_header grub_efi_dhcp6_header_t; ++ ++struct grub_efi_dhcp6_packet { ++ grub_efi_uint32_t size; ++ grub_efi_uint32_t length; ++ struct { ++ grub_efi_dhcp6_header_t header; ++ grub_efi_uint8_t option[1]; ++ } dhcp6; ++} GRUB_PACKED; ++ ++typedef struct grub_efi_dhcp6_packet grub_efi_dhcp6_packet_t; ++ ++struct grub_efi_dhcp6_ia_address { ++ grub_efi_ipv6_address_t ip_address; ++ grub_efi_uint32_t preferred_lifetime; ++ grub_efi_uint32_t valid_lifetime; ++}; ++ ++typedef struct grub_efi_dhcp6_ia_address grub_efi_dhcp6_ia_address_t; ++ ++enum grub_efi_dhcp6_state { ++ GRUB_EFI_DHCP6_INIT, ++ GRUB_EFI_DHCP6_SELECTING, ++ GRUB_EFI_DHCP6_REQUESTING, ++ GRUB_EFI_DHCP6_DECLINING, ++ GRUB_EFI_DHCP6_CONFIRMING, ++ GRUB_EFI_DHCP6_RELEASING, ++ GRUB_EFI_DHCP6_BOUND, ++ GRUB_EFI_DHCP6_RENEWING, ++ GRUB_EFI_DHCP6_REBINDING ++}; ++ ++typedef enum grub_efi_dhcp6_state grub_efi_dhcp6_state_t; ++ ++#define GRUB_EFI_DHCP6_IA_TYPE_NA 3 ++#define GRUB_EFI_DHCP6_IA_TYPE_TA 4 ++ ++struct grub_efi_dhcp6_ia_descriptor { ++ grub_efi_uint16_t type; ++ grub_efi_uint32_t ia_id; ++}; ++ ++typedef struct grub_efi_dhcp6_ia_descriptor grub_efi_dhcp6_ia_descriptor_t; ++ ++struct grub_efi_dhcp6_ia { ++ grub_efi_dhcp6_ia_descriptor_t descriptor; ++ grub_efi_dhcp6_state_t state; ++ grub_efi_dhcp6_packet_t *reply_packet; ++ grub_efi_uint32_t ia_address_count; ++ grub_efi_dhcp6_ia_address_t ia_address[1]; ++}; ++ ++typedef struct grub_efi_dhcp6_ia grub_efi_dhcp6_ia_t; ++ ++struct grub_efi_dhcp6_duid { ++ grub_efi_uint16_t length; ++ grub_efi_uint8_t duid[1]; ++}; ++ ++typedef struct grub_efi_dhcp6_duid grub_efi_dhcp6_duid_t; ++ ++struct grub_efi_dhcp6_mode_data { ++ grub_efi_dhcp6_duid_t *client_id; ++ grub_efi_dhcp6_ia_t *ia; ++}; ++ ++typedef struct grub_efi_dhcp6_mode_data grub_efi_dhcp6_mode_data_t; ++ ++struct grub_efi_dhcp6_config_data { ++ grub_efi_status_t (*dhcp6_callback) (grub_efi_dhcp6_protocol_t this, ++ void *context, ++ grub_efi_dhcp6_state_t current_state, ++ grub_efi_dhcp6_event_t dhcp6_event, ++ grub_efi_dhcp6_packet_t *packet, ++ grub_efi_dhcp6_packet_t **new_packet); ++ void *callback_context; ++ grub_efi_uint32_t option_count; ++ grub_efi_dhcp6_packet_option_t **option_list; ++ grub_efi_dhcp6_ia_descriptor_t ia_descriptor; ++ grub_efi_event_t ia_info_event; ++ grub_efi_boolean_t reconfigure_accept; ++ grub_efi_boolean_t rapid_commit; ++ grub_efi_dhcp6_retransmission_t *solicit_retransmission; ++}; ++ ++typedef struct grub_efi_dhcp6_config_data grub_efi_dhcp6_config_data_t; ++ ++struct grub_efi_dhcp6_protocol { ++ grub_efi_status_t (*get_mode_data) (grub_efi_dhcp6_protocol_t *this, ++ grub_efi_dhcp6_mode_data_t *dhcp6_mode_data, ++ grub_efi_dhcp6_config_data_t *dhcp6_config_data); ++ grub_efi_status_t (*configure) (grub_efi_dhcp6_protocol_t *this, ++ grub_efi_dhcp6_config_data_t *dhcp6_cfg_data); ++ grub_efi_status_t (*start) (grub_efi_dhcp6_protocol_t *this); ++ grub_efi_status_t (*info_request) (grub_efi_dhcp6_protocol_t *this, ++ grub_efi_boolean_t send_client_id, ++ grub_efi_dhcp6_packet_option_t *option_request, ++ grub_efi_uint32_t option_count, ++ grub_efi_dhcp6_packet_option_t *option_list[], ++ grub_efi_dhcp6_retransmission_t *retransmission, ++ grub_efi_event_t timeout_event, ++ grub_efi_status_t (*reply_callback) (grub_efi_dhcp6_protocol_t *this, ++ void *context, ++ grub_efi_dhcp6_packet_t *packet), ++ void *callback_context); ++ grub_efi_status_t (*renew_rebind) (grub_efi_dhcp6_protocol_t *this, ++ grub_efi_boolean_t rebind_request); ++ grub_efi_status_t (*decline) (grub_efi_dhcp6_protocol_t *this, ++ grub_efi_uint32_t address_count, ++ grub_efi_ipv6_address_t *addresses); ++ grub_efi_status_t (*release) (grub_efi_dhcp6_protocol_t *this, ++ grub_efi_uint32_t address_count, ++ grub_efi_ipv6_address_t *addresses); ++ grub_efi_status_t (*stop) (grub_efi_dhcp6_protocol_t *this); ++ grub_efi_status_t (*parse) (grub_efi_dhcp6_protocol_t *this, ++ grub_efi_dhcp6_packet_t *packet, ++ grub_efi_uint32_t *option_count, ++ grub_efi_dhcp6_packet_option_t *packet_option_list[]); ++}; ++ ++#endif /* ! GRUB_EFI_DHCP_HEADER */ +diff --git a/include/grub/efi/http.h b/include/grub/efi/http.h +new file mode 100644 +index 00000000000..c5e9a89f505 +--- /dev/null ++++ b/include/grub/efi/http.h +@@ -0,0 +1,215 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_EFI_HTTP_HEADER ++#define GRUB_EFI_HTTP_HEADER 1 ++ ++#include ++#include ++#include ++ ++#define GRUB_EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID \ ++ { 0xbdc8e6af, 0xd9bc, 0x4379, \ ++ { 0xa7, 0x2a, 0xe0, 0xc4, 0xe7, 0x5d, 0xae, 0x1c } \ ++ } ++ ++#define GRUB_EFI_HTTP_PROTOCOL_GUID \ ++ { 0x7A59B29B, 0x910B, 0x4171, \ ++ { 0x82, 0x42, 0xA8, 0x5A, 0x0D, 0xF2, 0x5B, 0x5B } \ ++ } ++ ++#define EFIHTTP_WAIT_TIME 10000 // 10000ms = 10s ++#define EFIHTTP_RX_BUF_LEN 10240 ++ ++//****************************************** ++// Protocol Interface Structure ++//****************************************** ++struct grub_efi_http; ++ ++//****************************************** ++// EFI_HTTP_VERSION ++//****************************************** ++typedef enum { ++ GRUB_EFI_HTTPVERSION10, ++ GRUB_EFI_HTTPVERSION11, ++ GRUB_EFI_HTTPVERSIONUNSUPPORTED ++} grub_efi_http_version_t; ++ ++//****************************************** ++// EFI_HTTPv4_ACCESS_POINT ++//****************************************** ++typedef struct { ++ grub_efi_boolean_t use_default_address; ++ grub_efi_ipv4_address_t local_address; ++ grub_efi_ipv4_address_t local_subnet; ++ grub_efi_uint16_t local_port; ++} grub_efi_httpv4_access_point_t; ++ ++//****************************************** ++// EFI_HTTPv6_ACCESS_POINT ++//****************************************** ++typedef struct { ++ grub_efi_ipv6_address_t local_address; ++ grub_efi_uint16_t local_port; ++} grub_efi_httpv6_access_point_t; ++ ++//****************************************** ++// EFI_HTTP_CONFIG_DATA ++//****************************************** ++typedef struct { ++ grub_efi_http_version_t http_version; ++ grub_efi_uint32_t timeout_millisec; ++ grub_efi_boolean_t local_address_is_ipv6; ++ union { ++ grub_efi_httpv4_access_point_t *ipv4_node; ++ grub_efi_httpv6_access_point_t *ipv6_node; ++ } access_point; ++} grub_efi_http_config_data_t; ++ ++//****************************************** ++// EFI_HTTP_METHOD ++//****************************************** ++typedef enum { ++ GRUB_EFI_HTTPMETHODGET, ++ GRUB_EFI_HTTPMETHODPOST, ++ GRUB_EFI_HTTPMETHODPATCH, ++ GRUB_EFI_HTTPMETHODOPTIONS, ++ GRUB_EFI_HTTPMETHODCONNECT, ++ GRUB_EFI_HTTPMETHODHEAD, ++ GRUB_EFI_HTTPMETHODPUT, ++ GRUB_EFI_HTTPMETHODDELETE, ++ GRUB_EFI_HTTPMETHODTRACE, ++} grub_efi_http_method_t; ++ ++//****************************************** ++// EFI_HTTP_REQUEST_DATA ++//****************************************** ++typedef struct { ++ grub_efi_http_method_t method; ++ grub_efi_char16_t *url; ++} grub_efi_http_request_data_t; ++ ++typedef enum { ++ GRUB_EFI_HTTP_STATUS_UNSUPPORTED_STATUS = 0, ++ GRUB_EFI_HTTP_STATUS_100_CONTINUE, ++ GRUB_EFI_HTTP_STATUS_101_SWITCHING_PROTOCOLS, ++ GRUB_EFI_HTTP_STATUS_200_OK, ++ GRUB_EFI_HTTP_STATUS_201_CREATED, ++ GRUB_EFI_HTTP_STATUS_202_ACCEPTED, ++ GRUB_EFI_HTTP_STATUS_203_NON_AUTHORITATIVE_INFORMATION, ++ GRUB_EFI_HTTP_STATUS_204_NO_CONTENT, ++ GRUB_EFI_HTTP_STATUS_205_RESET_CONTENT, ++ GRUB_EFI_HTTP_STATUS_206_PARTIAL_CONTENT, ++ GRUB_EFI_HTTP_STATUS_300_MULTIPLE_CHIOCES, ++ GRUB_EFI_HTTP_STATUS_301_MOVED_PERMANENTLY, ++ GRUB_EFI_HTTP_STATUS_302_FOUND, ++ GRUB_EFI_HTTP_STATUS_303_SEE_OTHER, ++ GRUB_EFI_HTTP_STATUS_304_NOT_MODIFIED, ++ GRUB_EFI_HTTP_STATUS_305_USE_PROXY, ++ GRUB_EFI_HTTP_STATUS_307_TEMPORARY_REDIRECT, ++ GRUB_EFI_HTTP_STATUS_400_BAD_REQUEST, ++ GRUB_EFI_HTTP_STATUS_401_UNAUTHORIZED, ++ GRUB_EFI_HTTP_STATUS_402_PAYMENT_REQUIRED, ++ GRUB_EFI_HTTP_STATUS_403_FORBIDDEN, ++ GRUB_EFI_HTTP_STATUS_404_NOT_FOUND, ++ GRUB_EFI_HTTP_STATUS_405_METHOD_NOT_ALLOWED, ++ GRUB_EFI_HTTP_STATUS_406_NOT_ACCEPTABLE, ++ GRUB_EFI_HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED, ++ GRUB_EFI_HTTP_STATUS_408_REQUEST_TIME_OUT, ++ GRUB_EFI_HTTP_STATUS_409_CONFLICT, ++ GRUB_EFI_HTTP_STATUS_410_GONE, ++ GRUB_EFI_HTTP_STATUS_411_LENGTH_REQUIRED, ++ GRUB_EFI_HTTP_STATUS_412_PRECONDITION_FAILED, ++ GRUB_EFI_HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE, ++ GRUB_EFI_HTTP_STATUS_414_REQUEST_URI_TOO_LARGE, ++ GRUB_EFI_HTTP_STATUS_415_UNSUPPORTED_MEDIA_TYPE, ++ GRUB_EFI_HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED, ++ GRUB_EFI_HTTP_STATUS_417_EXPECTATION_FAILED, ++ GRUB_EFI_HTTP_STATUS_500_INTERNAL_SERVER_ERROR, ++ GRUB_EFI_HTTP_STATUS_501_NOT_IMPLEMENTED, ++ GRUB_EFI_HTTP_STATUS_502_BAD_GATEWAY, ++ GRUB_EFI_HTTP_STATUS_503_SERVICE_UNAVAILABLE, ++ GRUB_EFI_HTTP_STATUS_504_GATEWAY_TIME_OUT, ++ GRUB_EFI_HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED ++} grub_efi_http_status_code_t; ++ ++//****************************************** ++// EFI_HTTP_RESPONSE_DATA ++//****************************************** ++typedef struct { ++ grub_efi_http_status_code_t status_code; ++} grub_efi_http_response_data_t; ++ ++//****************************************** ++// EFI_HTTP_HEADER ++//****************************************** ++typedef struct { ++ grub_efi_char8_t *field_name; ++ grub_efi_char8_t *field_value; ++} grub_efi_http_header_t; ++ ++//****************************************** ++// EFI_HTTP_MESSAGE ++//****************************************** ++typedef struct { ++ union { ++ grub_efi_http_request_data_t *request; ++ grub_efi_http_response_data_t *response; ++ } data; ++ grub_efi_uint32_t header_count; ++ grub_efi_http_header_t *headers; ++ grub_efi_uint32_t body_length; ++ void *body; ++} grub_efi_http_message_t; ++ ++//****************************************** ++// EFI_HTTP_TOKEN ++//****************************************** ++typedef struct { ++ grub_efi_event_t event; ++ grub_efi_status_t status; ++ grub_efi_http_message_t *message; ++} grub_efi_http_token_t; ++ ++struct grub_efi_http { ++ grub_efi_status_t ++ (*get_mode_data) (struct grub_efi_http *this, ++ grub_efi_http_config_data_t *http_config_data); ++ ++ grub_efi_status_t ++ (*configure) (struct grub_efi_http *this, ++ grub_efi_http_config_data_t *http_config_data); ++ ++ grub_efi_status_t ++ (*request) (struct grub_efi_http *this, ++ grub_efi_http_token_t *token); ++ ++ grub_efi_status_t ++ (*cancel) (struct grub_efi_http *this, ++ grub_efi_http_token_t *token); ++ ++ grub_efi_status_t ++ (*response) (struct grub_efi_http *this, ++ grub_efi_http_token_t *token); ++ ++ grub_efi_status_t ++ (*poll) (struct grub_efi_http *this); ++}; ++typedef struct grub_efi_http grub_efi_http_t; ++ ++#endif /* !GRUB_EFI_HTTP_HEADER */ +diff --git a/include/grub/net/efi.h b/include/grub/net/efi.h +new file mode 100644 +index 00000000000..de90d223e8e +--- /dev/null ++++ b/include/grub/net/efi.h +@@ -0,0 +1,144 @@ ++#ifndef GRUB_NET_EFI_HEADER ++#define GRUB_NET_EFI_HEADER 1 ++ ++#include ++#include ++#include ++#include ++ ++typedef struct grub_efi_net_interface grub_efi_net_interface_t; ++typedef struct grub_efi_net_ip_config grub_efi_net_ip_config_t; ++typedef union grub_efi_net_ip_address grub_efi_net_ip_address_t; ++typedef struct grub_efi_net_ip_manual_address grub_efi_net_ip_manual_address_t; ++ ++struct grub_efi_net_interface ++{ ++ char *name; ++ int prefer_ip6; ++ struct grub_efi_net_device *dev; ++ struct grub_efi_net_io *io; ++ grub_efi_net_ip_config_t *ip_config; ++ int io_type; ++ struct grub_efi_net_interface *next; ++}; ++ ++#define efi_net_interface_get_hw_address(inf) inf->ip_config->get_hw_address (inf->dev) ++#define efi_net_interface_get_address(inf) inf->ip_config->get_address (inf->dev) ++#define efi_net_interface_get_route_table(inf) inf->ip_config->get_route_table (inf->dev) ++#define efi_net_interface_set_address(inf, addr, with_subnet) inf->ip_config->set_address (inf->dev, addr, with_subnet) ++#define efi_net_interface_set_gateway(inf, addr) inf->ip_config->set_gateway (inf->dev, addr) ++#define efi_net_interface_set_dns(inf, addr) inf->ip_config->set_dns (inf->dev, addr) ++ ++struct grub_efi_net_ip_config ++{ ++ char * (*get_hw_address) (struct grub_efi_net_device *dev); ++ char * (*get_address) (struct grub_efi_net_device *dev); ++ char ** (*get_route_table) (struct grub_efi_net_device *dev); ++ grub_efi_net_interface_t * (*best_interface) (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *address); ++ int (*set_address) (struct grub_efi_net_device *dev, grub_efi_net_ip_manual_address_t *net_ip, int with_subnet); ++ int (*set_gateway) (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *address); ++ int (*set_dns) (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *dns); ++}; ++ ++union grub_efi_net_ip_address ++{ ++ grub_efi_ipv4_address_t ip4; ++ grub_efi_ipv6_address_t ip6; ++}; ++ ++struct grub_efi_net_ip_manual_address ++{ ++ int is_ip6; ++ union ++ { ++ grub_efi_ip4_config2_manual_address_t ip4; ++ grub_efi_ip6_config_manual_address_t ip6; ++ }; ++}; ++ ++struct grub_efi_net_device ++{ ++ grub_efi_handle_t handle; ++ grub_efi_ip4_config2_protocol_t *ip4_config; ++ grub_efi_ip6_config_protocol_t *ip6_config; ++ grub_efi_handle_t http_handle; ++ grub_efi_http_t *http; ++ grub_efi_handle_t ip4_pxe_handle; ++ grub_efi_pxe_t *ip4_pxe; ++ grub_efi_handle_t ip6_pxe_handle; ++ grub_efi_pxe_t *ip6_pxe; ++ grub_efi_handle_t dhcp4_handle; ++ grub_efi_dhcp4_protocol_t *dhcp4; ++ grub_efi_handle_t dhcp6_handle; ++ grub_efi_dhcp6_protocol_t *dhcp6; ++ char *card_name; ++ grub_efi_net_interface_t *net_interfaces; ++ struct grub_efi_net_device *next; ++}; ++ ++struct grub_efi_net_io ++{ ++ void (*configure) (struct grub_efi_net_device *dev, int prefer_ip6); ++ grub_err_t (*open) (struct grub_efi_net_device *dev, ++ int prefer_ip6, ++ grub_file_t file, ++ const char *filename, ++ int type); ++ grub_ssize_t (*read) (struct grub_efi_net_device *dev, ++ int prefer_ip6, ++ grub_file_t file, ++ char *buf, ++ grub_size_t len); ++ grub_err_t (*close) (struct grub_efi_net_device *dev, ++ int prefer_ip6, ++ grub_file_t file); ++}; ++ ++extern struct grub_efi_net_device *net_devices; ++ ++extern struct grub_efi_net_io io_http; ++extern struct grub_efi_net_io io_pxe; ++ ++extern grub_efi_net_ip_config_t *efi_net_ip4_config; ++extern grub_efi_net_ip_config_t *efi_net_ip6_config; ++ ++char * ++grub_efi_ip4_address_to_string (grub_efi_ipv4_address_t *address); ++ ++char * ++grub_efi_ip6_address_to_string (grub_efi_pxe_ipv6_address_t *address); ++ ++char * ++grub_efi_hw_address_to_string (grub_efi_uint32_t hw_address_size, grub_efi_mac_address_t hw_address); ++ ++int ++grub_efi_string_to_ip4_address (const char *val, grub_efi_ipv4_address_t *address, const char **rest); ++ ++int ++grub_efi_string_to_ip6_address (const char *val, grub_efi_ipv6_address_t *address, const char **rest); ++ ++char * ++grub_efi_ip6_interface_name (struct grub_efi_net_device *dev); ++ ++char * ++grub_efi_ip4_interface_name (struct grub_efi_net_device *dev); ++ ++grub_efi_net_interface_t * ++grub_efi_net_create_interface (struct grub_efi_net_device *dev, ++ const char *interface_name, ++ grub_efi_net_ip_manual_address_t *net_ip, ++ int has_subnet); ++ ++int grub_efi_net_fs_init (void); ++void grub_efi_net_fs_fini (void); ++int grub_efi_net_boot_from_https (void); ++int grub_efi_net_boot_from_opa (void); ++ ++extern grub_command_func_t grub_efi_net_list_routes; ++extern grub_command_func_t grub_efi_net_list_cards; ++extern grub_command_func_t grub_efi_net_list_addrs; ++extern grub_command_func_t grub_efi_net_add_addr; ++extern grub_command_func_t grub_efi_net_bootp; ++extern grub_command_func_t grub_efi_net_bootp6; ++ ++#endif /* ! GRUB_NET_EFI_HEADER */ diff --git a/SOURCES/0266-efinet-Setting-network-from-UEFI-device-path.patch b/SOURCES/0266-efinet-Setting-network-from-UEFI-device-path.patch new file mode 100644 index 0000000..1084075 --- /dev/null +++ b/SOURCES/0266-efinet-Setting-network-from-UEFI-device-path.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Sun, 10 Jul 2016 23:46:31 +0800 +Subject: [PATCH] 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 +Signed-off-by: Ken Lin +--- + grub-core/net/drivers/efi/efinet.c | 14 +++++--------- + 1 file changed, 5 insertions(+), 9 deletions(-) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index 3bea6221745..a161e7a5f26 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -475,9 +475,6 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u + grub_err_t err; + + ddp = grub_efi_duplicate_device_path (dp); +- if (!ddp) +- return NULL; +- + ldp = grub_efi_find_last_device_path (ddp); + + if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE +@@ -754,7 +751,7 @@ 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; ++ struct grub_efi_pxe_mode *pxe_mode = NULL; + grub_uint8_t *packet_buf; + grub_size_t packet_bufsz ; + int ipv6; +@@ -841,11 +838,10 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + if (ipv6) + { + grub_dprintf ("efinet", "using ipv6 and dhcpv6\n"); +- grub_dprintf ("efinet", "dhcp_ack_received: %s%s\n", +- pxe_mode->dhcp_ack_received ? "yes" : "no", +- pxe_mode->dhcp_ack_received ? "" : " cannot continue"); +- if (!pxe_mode->dhcp_ack_received) +- continue; ++ if (pxe_mode) ++ grub_dprintf ("efinet", "dhcp_ack_received: %s%s\n", ++ pxe_mode->dhcp_ack_received ? "yes" : "no", ++ pxe_mode->dhcp_ack_received ? "" : " cannot continue"); + + grub_net_configure_by_dhcpv6_reply (card->name, card, 0, + (struct grub_net_dhcp6_packet *) diff --git a/SOURCES/0267-AUDIT-0-http-boot-tracker-bug.patch b/SOURCES/0267-AUDIT-0-http-boot-tracker-bug.patch new file mode 100644 index 0000000..d6b2107 --- /dev/null +++ b/SOURCES/0267-AUDIT-0-http-boot-tracker-bug.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sebastian Krahmer +Date: Tue, 28 Nov 2017 17:24:38 +0800 +Subject: [PATCH] AUDIT-0: http boot tracker bug + +Fixing a memory leak in case of error, and a integer overflow, leading to a +heap overflow due to overly large chunk sizes. + +We need to check against some maximum value, otherwise values like 0xffffffff +will eventually lead in the allocation functions to small sized buffers, since +the len is rounded up to the next reasonable alignment. The following memcpy +will then smash the heap, leading to RCE. + +This is no big issue for pure http boot, since its going to execute an +untrusted kernel anyway, but it will break trusted boot scenarios, where only +signed code is allowed to be executed. + +Signed-off-by: Michael Chang +--- + grub-core/net/efi/net.c | 4 +++- + grub-core/net/http.c | 5 ++++- + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/grub-core/net/efi/net.c b/grub-core/net/efi/net.c +index 9e0078ac1c6..2bf15447fd5 100644 +--- a/grub-core/net/efi/net.c ++++ b/grub-core/net/efi/net.c +@@ -645,8 +645,10 @@ grub_efihttp_chunk_read (grub_file_t file, char *buf, + + rd = efi_net_interface (read, file, chunk, sz); + +- if (rd <= 0) ++ if (rd <= 0) { ++ grub_free (chunk); + return rd; ++ } + + if (buf) + { +diff --git a/grub-core/net/http.c b/grub-core/net/http.c +index 2b46e4672fc..82515f352dd 100644 +--- a/grub-core/net/http.c ++++ b/grub-core/net/http.c +@@ -31,7 +31,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); + + enum + { +- HTTP_PORT = 80 ++ HTTP_PORT = 80, ++ HTTP_MAX_CHUNK_SIZE = 0x80000000 + }; + + +@@ -78,6 +79,8 @@ parse_line (grub_file_t file, http_data_t data, char *ptr, grub_size_t len) + if (data->in_chunk_len == 2) + { + data->chunk_rem = grub_strtoul (ptr, 0, 16); ++ if (data->chunk_rem > HTTP_MAX_CHUNK_SIZE) ++ return GRUB_ERR_NET_PACKET_TOO_BIG; + grub_errno = GRUB_ERR_NONE; + if (data->chunk_rem == 0) + { diff --git a/SOURCES/0268-xfs-accept-filesystem-with-sparse-inodes.patch b/SOURCES/0268-xfs-accept-filesystem-with-sparse-inodes.patch new file mode 100644 index 0000000..84502ae --- /dev/null +++ b/SOURCES/0268-xfs-accept-filesystem-with-sparse-inodes.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Eric Sandeen +Date: Tue, 15 May 2018 14:55:55 -0500 +Subject: [PATCH] xfs: accept filesystem with sparse inodes + +The sparse inode metadata format became a mkfs.xfs default in +xfsprogs-4.16.0, and such filesystems are now rejected by grub as +containing an incompatible feature. + +In essence, this feature allows xfs to allocate inodes into fragmented +freespace. (Without this feature, if xfs could not allocate contiguous +space for 64 new inodes, inode creation would fail.) + +In practice, the disk format change is restricted to the inode btree, +which as far as I can tell is not used by grub. If all you're doing +today is parsing a directory, reading an inode number, and converting +that inode number to a disk location, then ignoring this feature +should be fine, so I've added it to XFS_SB_FEAT_INCOMPAT_SUPPORTED + +I did some brief testing of this patch by hacking up the regression +tests to completely fragment freespace on the test xfs filesystem, and +then write a large-ish number of inodes to consume any existing +contiguous 64-inode chunk. This way any files the grub tests add and +traverse would be in such a fragmented inode allocation. Tests passed, +but I'm not sure how to cleanly integrate that into the test harness. + +Signed-off-by: Eric Sandeen +--- + grub-core/fs/xfs.c | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index 72492915533..852155b1bf3 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -76,8 +76,22 @@ GRUB_MOD_LICENSE ("GPLv3+"); + + /* incompat feature flags */ + #define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */ ++#define XFS_SB_FEAT_INCOMPAT_SPINODES (1 << 1) /* sparse inode chunks */ ++#define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */ ++ ++/* ++ * Directory entries with ftype are explicitly handled by grub code. ++ * ++ * We do not currently verify metadata UUID, so it is safe to read filesystems ++ * with the XFS_SB_FEAT_INCOMPAT_META_UUID feature. ++ * ++ * We do not currently read the inode btrees, so it is safe to read filesystems ++ * with the XFS_SB_FEAT_INCOMPAT_SPINODES feature. ++ */ + #define XFS_SB_FEAT_INCOMPAT_SUPPORTED \ +- (XFS_SB_FEAT_INCOMPAT_FTYPE) ++ (XFS_SB_FEAT_INCOMPAT_FTYPE | \ ++ XFS_SB_FEAT_INCOMPAT_SPINODES | \ ++ XFS_SB_FEAT_INCOMPAT_META_UUID) + + struct grub_xfs_sblock + { diff --git a/SOURCES/0269-grub-core-video-efi_gop.c-Add-support-for-BLT_ONLY-a.patch b/SOURCES/0269-grub-core-video-efi_gop.c-Add-support-for-BLT_ONLY-a.patch new file mode 100644 index 0000000..33cde3b --- /dev/null +++ b/SOURCES/0269-grub-core-video-efi_gop.c-Add-support-for-BLT_ONLY-a.patch @@ -0,0 +1,56 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alexander Graf +Date: Wed, 1 Feb 2017 23:10:45 +0100 +Subject: [PATCH] grub-core/video/efi_gop.c: Add support for BLT_ONLY adapters + +EFI GOP has support for multiple different bitness types of frame buffers +and for a special "BLT only" type which is always defined to be RGBx. + +Because grub2 doesn't ever directly access the frame buffer but instead +only renders graphics via the BLT interface anyway, we can easily support +these adapters. + +The reason this has come up now is the emerging support for virtio-gpu +in OVMF. That adapter does not have the notion of a memory mapped frame +buffer and thus is BLT only. + +Signed-off-by: Alexander Graf +--- + grub-core/video/efi_gop.c | 2 ++ + include/grub/efi/graphics_output.h | 3 ++- + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/grub-core/video/efi_gop.c b/grub-core/video/efi_gop.c +index 7f9d1c2dfa1..c9e40e8d4e9 100644 +--- a/grub-core/video/efi_gop.c ++++ b/grub-core/video/efi_gop.c +@@ -121,6 +121,7 @@ grub_video_gop_get_bpp (struct grub_efi_gop_mode_info *in) + { + case GRUB_EFI_GOT_BGRA8: + case GRUB_EFI_GOT_RGBA8: ++ case GRUB_EFI_GOT_BLT_ONLY: + return 32; + + case GRUB_EFI_GOT_BITMASK: +@@ -187,6 +188,7 @@ grub_video_gop_fill_real_mode_info (unsigned mode, + switch (in->pixel_format) + { + case GRUB_EFI_GOT_RGBA8: ++ case GRUB_EFI_GOT_BLT_ONLY: + out->red_mask_size = 8; + out->red_field_pos = 0; + out->green_mask_size = 8; +diff --git a/include/grub/efi/graphics_output.h b/include/grub/efi/graphics_output.h +index 12977741192..e4388127c66 100644 +--- a/include/grub/efi/graphics_output.h ++++ b/include/grub/efi/graphics_output.h +@@ -28,7 +28,8 @@ typedef enum + { + GRUB_EFI_GOT_RGBA8, + GRUB_EFI_GOT_BGRA8, +- GRUB_EFI_GOT_BITMASK ++ GRUB_EFI_GOT_BITMASK, ++ GRUB_EFI_GOT_BLT_ONLY, + } + grub_efi_gop_pixel_format_t; + diff --git a/SOURCES/0270-efi-uga-use-64-bit-for-fb_base.patch b/SOURCES/0270-efi-uga-use-64-bit-for-fb_base.patch new file mode 100644 index 0000000..391bdb2 --- /dev/null +++ b/SOURCES/0270-efi-uga-use-64-bit-for-fb_base.patch @@ -0,0 +1,105 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Wed, 16 May 2018 13:06:04 -0400 +Subject: [PATCH] efi/uga: use 64 bit for fb_base + +We get 64 bit from PCI BAR but then truncate by assigning to 32 bit. +Make sure to check that pointer does not overflow on 32 bit platform. + +Closes: 50931 +--- + grub-core/video/efi_uga.c | 31 ++++++++++++++++--------------- + 1 file changed, 16 insertions(+), 15 deletions(-) + +diff --git a/grub-core/video/efi_uga.c b/grub-core/video/efi_uga.c +index 464ede874da..1d4091c5631 100644 +--- a/grub-core/video/efi_uga.c ++++ b/grub-core/video/efi_uga.c +@@ -34,7 +34,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); + + static grub_efi_guid_t uga_draw_guid = GRUB_EFI_UGA_DRAW_GUID; + static struct grub_efi_uga_draw_protocol *uga; +-static grub_uint32_t uga_fb; ++static grub_uint64_t uga_fb; + static grub_uint32_t uga_pitch; + + static struct +@@ -52,7 +52,7 @@ static struct + #define FBTEST_COUNT 8 + + static int +-find_line_len (grub_uint32_t *fb_base, grub_uint32_t *line_len) ++find_line_len (grub_uint64_t *fb_base, grub_uint32_t *line_len) + { + grub_uint32_t *base = (grub_uint32_t *) (grub_addr_t) *fb_base; + int i; +@@ -67,7 +67,7 @@ find_line_len (grub_uint32_t *fb_base, grub_uint32_t *line_len) + { + if ((base[j] & RGB_MASK) == RGB_MAGIC) + { +- *fb_base = (grub_uint32_t) (grub_addr_t) base; ++ *fb_base = (grub_uint64_t) (grub_addr_t) base; + *line_len = j << 2; + + return 1; +@@ -84,7 +84,7 @@ find_line_len (grub_uint32_t *fb_base, grub_uint32_t *line_len) + /* Context for find_framebuf. */ + struct find_framebuf_ctx + { +- grub_uint32_t *fb_base; ++ grub_uint64_t *fb_base; + grub_uint32_t *line_len; + int found; + }; +@@ -120,7 +120,9 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data) + if (i == 5) + break; + +- old_bar2 = grub_pci_read (addr + 4); ++ i++; ++ addr += 4; ++ old_bar2 = grub_pci_read (addr); + } + else + old_bar2 = 0; +@@ -129,10 +131,15 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data) + base64 <<= 32; + base64 |= (old_bar1 & GRUB_PCI_ADDR_MEM_MASK); + +- grub_dprintf ("fb", "%s(%d): 0x%llx\n", ++ grub_dprintf ("fb", "%s(%d): 0x%" PRIxGRUB_UINT64_T "\n", + ((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) ? +- "VMEM" : "MMIO"), i, +- (unsigned long long) base64); ++ "VMEM" : "MMIO"), type == GRUB_PCI_ADDR_MEM_TYPE_64 ? i - 1 : i, ++ base64); ++ ++#if GRUB_CPU_SIZEOF_VOID_P == 4 ++ if (old_bar2) ++ continue; ++#endif + + if ((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) && (! ctx->found)) + { +@@ -140,12 +147,6 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data) + if (find_line_len (ctx->fb_base, ctx->line_len)) + ctx->found++; + } +- +- if (type == GRUB_PCI_ADDR_MEM_TYPE_64) +- { +- i++; +- addr += 4; +- } + } + } + +@@ -153,7 +154,7 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data) + } + + static int +-find_framebuf (grub_uint32_t *fb_base, grub_uint32_t *line_len) ++find_framebuf (grub_uint64_t *fb_base, grub_uint32_t *line_len) + { + struct find_framebuf_ctx ctx = { + .fb_base = fb_base, diff --git a/SOURCES/0271-Fix-grub-setpassword-o-s-output-path.patch b/SOURCES/0271-Fix-grub-setpassword-o-s-output-path.patch new file mode 100644 index 0000000..6bf5751 --- /dev/null +++ b/SOURCES/0271-Fix-grub-setpassword-o-s-output-path.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andy Lutomirski +Date: Sun, 11 Jun 2017 19:17:40 -0400 +Subject: [PATCH] Fix grub-setpassword -o's output path + +The output path is set up in the command line parsing, but completely ignored +in the code that actually writes the files. This patch fixes that. + +Signed-off-by: Peter Jones +--- + util/grub-setpassword.in | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/util/grub-setpassword.in b/util/grub-setpassword.in +index d7924af5192..9ca7114f904 100755 +--- a/util/grub-setpassword.in ++++ b/util/grub-setpassword.in +@@ -117,11 +117,11 @@ fi + + # on the ESP, these will fail to set the permissions, but it's okay because + # the directory is protected. +-install -m 0600 /dev/null "${grubdir}/user.cfg" 2>/dev/null || : +-chmod 0600 "${grubdir}/user.cfg" 2>/dev/null || : +-echo "GRUB2_PASSWORD=${MYPASS}" > "${grubdir}/user.cfg" ++install -m 0600 /dev/null "${OUTPUT_PATH}/user.cfg" 2>/dev/null || : ++chmod 0600 "${OUTPUT_PATH}/user.cfg" 2>/dev/null || : ++echo "GRUB2_PASSWORD=${MYPASS}" > "${OUTPUT_PATH}/user.cfg" + +-if ! grep -q "^### BEGIN /etc/grub.d/01_users ###$" "${grubdir}/grub.cfg"; then ++if ! grep -q "^### BEGIN /etc/grub.d/01_users ###$" "${OUTPUT_PATH}/grub.cfg"; then + echo "WARNING: The current configuration lacks password support!" + echo "Update your configuration with @grub_mkconfig@ to support this feature." + fi diff --git a/SOURCES/0272-Verify-modules-on-build-time-rather-than-failing-in-.patch b/SOURCES/0272-Verify-modules-on-build-time-rather-than-failing-in-.patch new file mode 100644 index 0000000..53423db --- /dev/null +++ b/SOURCES/0272-Verify-modules-on-build-time-rather-than-failing-in-.patch @@ -0,0 +1,559 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Thu, 31 Dec 2015 13:09:15 +0100 +Subject: [PATCH] Verify modules on build-time rather than failing in runtime. + +--- + util/grub-module-verifier.c | 122 ++++++++++++++++ + util/grub-module-verifier32.c | 2 + + util/grub-module-verifier64.c | 2 + + util/grub-module-verifierXX.c | 315 +++++++++++++++++++++++++++++++++++++++++ + include/grub/module_verifier.h | 19 +++ + grub-core/Makefile.am | 6 +- + grub-core/genmod.sh.in | 5 +- + 7 files changed, 468 insertions(+), 3 deletions(-) + create mode 100644 util/grub-module-verifier.c + create mode 100644 util/grub-module-verifier32.c + create mode 100644 util/grub-module-verifier64.c + create mode 100644 util/grub-module-verifierXX.c + create mode 100644 include/grub/module_verifier.h + +diff --git a/util/grub-module-verifier.c b/util/grub-module-verifier.c +new file mode 100644 +index 00000000000..d2d6984033c +--- /dev/null ++++ b/util/grub-module-verifier.c +@@ -0,0 +1,122 @@ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++struct grub_module_verifier_arch archs[] = { ++ { "i386", 4, 0, EM_386, GRUB_MODULE_VERIFY_SUPPORTS_REL, (int[]){ ++ R_386_32, ++ R_386_PC32, ++ -1 ++ } }, ++ { "x86_64", 8, 0, EM_X86_64, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){ ++ R_X86_64_64, ++ R_X86_64_PC64, ++ /* R_X86_64_32, R_X86_64_32S, R_X86_64_PC32 are supported but shouldn't be used because of their limited range. */ ++ -1 ++ } }, ++ { "powerpc", 4, 1, EM_PPC, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){ ++ GRUB_ELF_R_PPC_ADDR16_LO, ++ GRUB_ELF_R_PPC_REL24, /* It has limited range but GRUB adds trampolines when necessarry. */ ++ GRUB_ELF_R_PPC_ADDR16_HA, ++ GRUB_ELF_R_PPC_ADDR32, ++ GRUB_ELF_R_PPC_REL32, ++ -1 ++ } }, ++ { "sparc64", 8, 1, EM_SPARCV9, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){ ++ R_SPARC_WDISP30, /* It has limited range but GRUB adds trampolines when necessarry. */ ++ R_SPARC_HH22, ++ R_SPARC_HM10, ++ R_SPARC_LM22, ++ R_SPARC_LO10, ++ R_SPARC_64, ++ R_SPARC_OLO10, ++ /* R_SPARC_32, R_SPARC_HI22 are supported but shouldn't be used because of their limited range. */ ++ -1 ++ } }, ++ { "ia64", 8, 0, EM_IA_64, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){ ++ R_IA64_PCREL21B, /* We should verify that it's pointing either ++ to a function or to a section in the same module. */ ++ R_IA64_SEGREL64LSB, ++ R_IA64_FPTR64LSB, ++ R_IA64_DIR64LSB, ++ R_IA64_PCREL64LSB, ++ R_IA64_GPREL22, /* We should verify that it's pointing to a section in the same module. */ ++ R_IA64_LTOFF22X, ++ R_IA64_LTOFF22, ++ R_IA64_LTOFF_FPTR22, ++ R_IA64_LDXMOV, ++ -1 ++ } }, ++ { "mipsel", 4, 0, EM_MIPS, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){ ++ R_MIPS_HI16, ++ R_MIPS_LO16, ++ R_MIPS_32, ++ R_MIPS_GPREL32, ++ R_MIPS_26, ++ R_MIPS_GOT16, ++ R_MIPS_CALL16, ++ R_MIPS_JALR, ++ -1 ++ } }, ++ { "mips", 4, 1, EM_MIPS, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){ ++ R_MIPS_HI16, ++ R_MIPS_LO16, ++ R_MIPS_32, ++ R_MIPS_GPREL32, ++ R_MIPS_26, ++ R_MIPS_GOT16, ++ R_MIPS_CALL16, ++ R_MIPS_JALR, ++ -1 ++ } }, ++ { "arm", 4, 0, EM_ARM, GRUB_MODULE_VERIFY_SUPPORTS_REL, (int[]){ ++ /* Some relocations are range-limited but trampolines are added when necessarry. */ ++ R_ARM_ABS32, ++ R_ARM_CALL, ++ R_ARM_JUMP24, ++ R_ARM_THM_CALL, ++ R_ARM_THM_JUMP24, ++ R_ARM_V4BX, ++ R_ARM_THM_MOVW_ABS_NC, ++ R_ARM_THM_MOVT_ABS, ++ R_ARM_THM_JUMP19, ++ -1 ++ } }, ++ { "arm64", 8, 0, EM_AARCH64, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){ ++ R_AARCH64_ABS64, ++ R_AARCH64_CALL26, ++ R_AARCH64_JUMP26, ++ -1 ++ } }, ++}; ++ ++ ++int ++main (int argc, char **argv) ++{ ++ size_t module_size; ++ unsigned arch; ++ char *module_img; ++ if (argc != 3) { ++ fprintf (stderr, "usage: %s FILE ARCH\n", argv[0]); ++ return 1; ++ } ++ ++ for (arch = 0; arch < ARRAY_SIZE(archs); arch++) ++ if (strcmp(archs[arch].name, argv[2]) == 0) ++ break; ++ if (arch == ARRAY_SIZE(archs)) ++ grub_util_error("unknown arch: %s", argv[2]); ++ ++ module_size = grub_util_get_image_size (argv[1]); ++ module_img = grub_util_read_image (argv[1]); ++ if (archs[arch].voidp_sizeof == 8) ++ grub_module_verify64(module_img, module_size, &archs[arch]); ++ else ++ grub_module_verify32(module_img, module_size, &archs[arch]); ++ return 0; ++} +diff --git a/util/grub-module-verifier32.c b/util/grub-module-verifier32.c +new file mode 100644 +index 00000000000..257229f8f08 +--- /dev/null ++++ b/util/grub-module-verifier32.c +@@ -0,0 +1,2 @@ ++#define MODULEVERIFIER_ELF32 1 ++#include "grub-module-verifierXX.c" +diff --git a/util/grub-module-verifier64.c b/util/grub-module-verifier64.c +new file mode 100644 +index 00000000000..4db6b4bedd1 +--- /dev/null ++++ b/util/grub-module-verifier64.c +@@ -0,0 +1,2 @@ ++#define MODULEVERIFIER_ELF64 1 ++#include "grub-module-verifierXX.c" +diff --git a/util/grub-module-verifierXX.c b/util/grub-module-verifierXX.c +new file mode 100644 +index 00000000000..904be27d39b +--- /dev/null ++++ b/util/grub-module-verifierXX.c +@@ -0,0 +1,315 @@ ++#include ++ ++#include ++#include ++#include ++ ++#if defined(MODULEVERIFIER_ELF32) ++# define SUFFIX(x) x ## 32 ++# define ELFCLASSXX ELFCLASS32 ++# define Elf_Ehdr Elf32_Ehdr ++# define Elf_Phdr Elf32_Phdr ++# define Elf_Nhdr Elf32_Nhdr ++# define Elf_Addr Elf32_Addr ++# define Elf_Sym Elf32_Sym ++# define Elf_Off Elf32_Off ++# define Elf_Shdr Elf32_Shdr ++# define Elf_Rela Elf32_Rela ++# define Elf_Rel Elf32_Rel ++# define Elf_Word Elf32_Word ++# define Elf_Half Elf32_Half ++# define Elf_Section Elf32_Section ++# define ELF_R_SYM(val) ELF32_R_SYM(val) ++# define ELF_R_TYPE(val) ELF32_R_TYPE(val) ++# define ELF_ST_TYPE(val) ELF32_ST_TYPE(val) ++#elif defined(MODULEVERIFIER_ELF64) ++# define SUFFIX(x) x ## 64 ++# define ELFCLASSXX ELFCLASS64 ++# define Elf_Ehdr Elf64_Ehdr ++# define Elf_Phdr Elf64_Phdr ++# define Elf_Nhdr Elf64_Nhdr ++# define Elf_Addr Elf64_Addr ++# define Elf_Sym Elf64_Sym ++# define Elf_Off Elf64_Off ++# define Elf_Shdr Elf64_Shdr ++# define Elf_Rela Elf64_Rela ++# define Elf_Rel Elf64_Rel ++# define Elf_Word Elf64_Word ++# define Elf_Half Elf64_Half ++# define Elf_Section Elf64_Section ++# define ELF_R_SYM(val) ELF64_R_SYM(val) ++# define ELF_R_TYPE(val) ELF64_R_TYPE(val) ++# define ELF_ST_TYPE(val) ELF64_ST_TYPE(val) ++#else ++#error "I'm confused" ++#endif ++ ++#define grub_target_to_host32(x) (grub_target_to_host32_real (arch, (x))) ++#define grub_host_to_target32(x) (grub_host_to_target32_real (arch, (x))) ++#define grub_target_to_host64(x) (grub_target_to_host64_real (arch, (x))) ++#define grub_host_to_target64(x) (grub_host_to_target64_real (arch, (x))) ++#define grub_host_to_target_addr(x) (grub_host_to_target_addr_real (arch, (x))) ++#define grub_target_to_host16(x) (grub_target_to_host16_real (arch, (x))) ++#define grub_host_to_target16(x) (grub_host_to_target16_real (arch, (x))) ++#define grub_target_to_host(val) grub_target_to_host_real(arch, (val)) ++ ++static inline grub_uint32_t ++grub_target_to_host32_real (const struct grub_module_verifier_arch *arch, ++ grub_uint32_t in) ++{ ++ if (arch->bigendian) ++ return grub_be_to_cpu32 (in); ++ else ++ return grub_le_to_cpu32 (in); ++} ++ ++static inline grub_uint64_t ++grub_target_to_host64_real (const struct grub_module_verifier_arch *arch, ++ grub_uint64_t in) ++{ ++ if (arch->bigendian) ++ return grub_be_to_cpu64 (in); ++ else ++ return grub_le_to_cpu64 (in); ++} ++ ++static inline grub_uint64_t ++grub_host_to_target64_real (const struct grub_module_verifier_arch *arch, ++ grub_uint64_t in) ++{ ++ if (arch->bigendian) ++ return grub_cpu_to_be64 (in); ++ else ++ return grub_cpu_to_le64 (in); ++} ++ ++static inline grub_uint32_t ++grub_host_to_target32_real (const struct grub_module_verifier_arch *arch, ++ grub_uint32_t in) ++{ ++ if (arch->bigendian) ++ return grub_cpu_to_be32 (in); ++ else ++ return grub_cpu_to_le32 (in); ++} ++ ++static inline grub_uint16_t ++grub_target_to_host16_real (const struct grub_module_verifier_arch *arch, ++ grub_uint16_t in) ++{ ++ if (arch->bigendian) ++ return grub_be_to_cpu16 (in); ++ else ++ return grub_le_to_cpu16 (in); ++} ++ ++static inline grub_uint16_t ++grub_host_to_target16_real (const struct grub_module_verifier_arch *arch, ++ grub_uint16_t in) ++{ ++ if (arch->bigendian) ++ return grub_cpu_to_be16 (in); ++ else ++ return grub_cpu_to_le16 (in); ++} ++ ++static inline grub_uint64_t ++grub_host_to_target_addr_real (const struct grub_module_verifier_arch *arch, grub_uint64_t in) ++{ ++ if (arch->voidp_sizeof == 8) ++ return grub_host_to_target64_real (arch, in); ++ else ++ return grub_host_to_target32_real (arch, in); ++} ++ ++static inline grub_uint64_t ++grub_target_to_host_real (const struct grub_module_verifier_arch *arch, grub_uint64_t in) ++{ ++ if (arch->voidp_sizeof == 8) ++ return grub_target_to_host64_real (arch, in); ++ else ++ return grub_target_to_host32_real (arch, in); ++} ++ ++ ++static Elf_Shdr * ++find_section (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e, const char *name) ++{ ++ Elf_Shdr *s; ++ const char *str; ++ unsigned i; ++ ++ s = (Elf_Shdr *) ((char *) e + grub_target_to_host (e->e_shoff) + grub_target_to_host16 (e->e_shstrndx) * grub_target_to_host16 (e->e_shentsize)); ++ str = (char *) e + grub_target_to_host (s->sh_offset); ++ ++ for (i = 0, s = (Elf_Shdr *) ((char *) e + grub_target_to_host (e->e_shoff)); ++ i < grub_target_to_host16 (e->e_shnum); ++ i++, s = (Elf_Shdr *) ((char *) s + grub_target_to_host16 (e->e_shentsize))) ++ if (strcmp (str + grub_target_to_host32 (s->sh_name), name) == 0) ++ return s; ++ return NULL; ++} ++ ++static void ++check_license (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e) ++{ ++ Elf_Shdr *s = find_section (arch, e, ".module_license"); ++ if (s && (strcmp ((char *) e + grub_target_to_host(s->sh_offset), "LICENSE=GPLv3") == 0 ++ || strcmp ((char *) e + grub_target_to_host(s->sh_offset), "LICENSE=GPLv3+") == 0 ++ || strcmp ((char *) e + grub_target_to_host(s->sh_offset), "LICENSE=GPLv2+") == 0)) ++ return; ++ grub_util_error ("incompatible license"); ++} ++ ++static void ++check_symbols (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e) ++{ ++ unsigned i; ++ Elf_Shdr *s, *sections; ++ Elf_Sym *sym; ++ const char *str; ++ Elf_Word size, entsize; ++ ++ sections = (Elf_Shdr *) ((char *) e + grub_target_to_host (e->e_shoff)); ++ for (i = 0, s = sections; ++ i < grub_target_to_host16 (e->e_shnum); ++ i++, s = (Elf_Shdr *) ((char *) s + grub_target_to_host16 (e->e_shentsize))) ++ if (grub_target_to_host32 (s->sh_type) == SHT_SYMTAB) ++ break; ++ ++ if (i == grub_target_to_host16 (e->e_shnum)) ++ grub_util_error ("no symbol table"); ++ ++ sym = (Elf_Sym *) ((char *) e + grub_target_to_host (s->sh_offset)); ++ size = grub_target_to_host (s->sh_size); ++ entsize = grub_target_to_host (s->sh_entsize); ++ ++ s = (Elf_Shdr *) ((char *) sections + grub_target_to_host16 (e->e_shentsize) * grub_target_to_host32 (s->sh_link)); ++ str = (char *) e + grub_target_to_host (s->sh_offset); ++ ++ for (i = 0; ++ i < size / entsize; ++ i++, sym = (Elf_Sym *) ((char *) sym + entsize)) ++ { ++ unsigned char type = ELF_ST_TYPE (sym->st_info); ++ ++ switch (type) ++ { ++ case STT_NOTYPE: ++ case STT_OBJECT: ++ case STT_FUNC: ++ case STT_SECTION: ++ case STT_FILE: ++ break; ++ ++ default: ++ return grub_util_error ("unknown symbol type `%d'", (int) type); ++ } ++ } ++} ++ ++/* Relocate symbols. */ ++static void ++section_check_relocations (const struct grub_module_verifier_arch *arch, void *ehdr, ++ Elf_Shdr *s, size_t target_seg_size) ++{ ++ Elf_Rel *rel, *max; ++ ++ for (rel = (Elf_Rel *) ((char *) ehdr + grub_target_to_host (s->sh_offset)), ++ max = (Elf_Rel *) ((char *) rel + grub_target_to_host (s->sh_size)); ++ rel < max; ++ rel = (Elf_Rel *) ((char *) rel + grub_target_to_host (s->sh_entsize))) ++ { ++ Elf_Word *addr; ++ Elf_Sym *sym; ++ unsigned i; ++ ++ if (target_seg_size < grub_target_to_host (rel->r_offset)) ++ grub_util_error ("reloc offset is out of the segment"); ++ ++ grub_uint32_t type = ELF_R_TYPE (grub_target_to_host (rel->r_info)); ++ ++ if (arch->machine == EM_SPARCV9) ++ type &= 0xff; ++ ++ for (i = 0; arch->supported_relocations[i] != -1; i++) ++ if (type == arch->supported_relocations[i]) ++ break; ++ if (arch->supported_relocations[i] == -1) ++ grub_util_error ("unsupported relocation 0x%x", type); ++ } ++} ++ ++static void ++check_relocations (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e) ++{ ++ Elf_Shdr *s; ++ unsigned i; ++ ++ for (i = 0, s = (Elf_Shdr *) ((char *) e + grub_target_to_host (e->e_shoff)); ++ i < grub_target_to_host16 (e->e_shnum); ++ i++, s = (Elf_Shdr *) ((char *) s + grub_target_to_host16 (e->e_shentsize))) ++ if (grub_target_to_host32 (s->sh_type) == SHT_REL || grub_target_to_host32 (s->sh_type) == SHT_RELA) ++ { ++ Elf_Shdr *ts; ++ ++ if (grub_target_to_host32 (s->sh_type) == SHT_REL && !(arch->flags & GRUB_MODULE_VERIFY_SUPPORTS_REL)) ++ grub_util_error ("unsupported SHT_REL"); ++ if (grub_target_to_host32 (s->sh_type) == SHT_RELA && !(arch->flags & GRUB_MODULE_VERIFY_SUPPORTS_RELA)) ++ grub_util_error ("unsupported SHT_RELA"); ++ ++ /* Find the target segment. */ ++ if (grub_target_to_host32 (s->sh_info) >= grub_target_to_host16 (e->e_shnum)) ++ grub_util_error ("orphaned reloc section"); ++ ts = (Elf_Shdr *) ((char *) e + grub_target_to_host (e->e_shoff) + grub_target_to_host32 (s->sh_info) * grub_target_to_host16 (e->e_shentsize)); ++ ++ section_check_relocations (arch, e, s, grub_target_to_host (ts->sh_size)); ++ } ++} ++ ++void ++SUFFIX(grub_module_verify) (void *module_img, size_t size, const struct grub_module_verifier_arch *arch) ++{ ++ Elf_Ehdr *e = module_img; ++ ++ /* Check the header size. */ ++ if (size < sizeof (Elf_Ehdr)) ++ grub_util_error ("ELF header smaller than expected"); ++ ++ /* Check the magic numbers. */ ++ if (e->e_ident[EI_MAG0] != ELFMAG0 ++ || e->e_ident[EI_MAG1] != ELFMAG1 ++ || e->e_ident[EI_MAG2] != ELFMAG2 ++ || e->e_ident[EI_MAG3] != ELFMAG3 ++ || e->e_ident[EI_VERSION] != EV_CURRENT ++ || grub_target_to_host32 (e->e_version) != EV_CURRENT) ++ grub_util_error ("invalid arch-independent ELF magic"); ++ ++ if (e->e_ident[EI_CLASS] != ELFCLASSXX ++ || e->e_ident[EI_DATA] != (arch->bigendian ? ELFDATA2MSB : ELFDATA2LSB) ++ || grub_target_to_host16 (e->e_machine) != arch->machine) ++ grub_util_error ("invalid arch-dependent ELF magic"); ++ ++ if (grub_target_to_host16 (e->e_type) != ET_REL) ++ { ++ grub_util_error ("this ELF file is not of the right type"); ++ } ++ ++ /* Make sure that every section is within the core. */ ++ if (size < grub_target_to_host (e->e_shoff) ++ + grub_target_to_host16 (e->e_shentsize) * grub_target_to_host16(e->e_shnum)) ++ { ++ grub_util_error ("ELF sections outside core"); ++ } ++ ++ check_license (arch, e); ++ ++ Elf_Shdr *s; ++ ++ s = find_section (arch, e, ".modname"); ++ if (!s) ++ grub_util_error ("no module name found"); ++ ++ check_symbols(arch, e); ++ check_relocations(arch, e); ++} +diff --git a/include/grub/module_verifier.h b/include/grub/module_verifier.h +new file mode 100644 +index 00000000000..9e3a2ba720f +--- /dev/null ++++ b/include/grub/module_verifier.h +@@ -0,0 +1,19 @@ ++#include ++#include ++ ++#include ++ ++#define GRUB_MODULE_VERIFY_SUPPORTS_REL 1 ++#define GRUB_MODULE_VERIFY_SUPPORTS_RELA 2 ++ ++struct grub_module_verifier_arch { ++ const char *name; ++ int voidp_sizeof; ++ int bigendian; ++ int machine; ++ int flags; ++ const int *supported_relocations; ++}; ++ ++void grub_module_verify64(void *module_img, size_t module_size, const struct grub_module_verifier_arch *arch); ++void grub_module_verify32(void *module_img, size_t module_size, const struct grub_module_verifier_arch *arch); +diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am +index be29e327f77..77205f16358 100644 +--- a/grub-core/Makefile.am ++++ b/grub-core/Makefile.am +@@ -39,6 +39,10 @@ gentrigtables$(BUILD_EXEEXT): gentrigtables.c + $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) $< $(BUILD_LIBM) + CLEANFILES += gentrigtables$(BUILD_EXEEXT) + ++build-grub-module-verifier$(BUILD_EXEEXT): $(top_srcdir)/util/grub-module-verifier.c $(top_srcdir)/util/grub-module-verifier32.c $(top_srcdir)/util/grub-module-verifier64.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c ++ $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_BUILD=1 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-module-verifier\" $^ ++CLEANFILES += build-grub-module-verifier$(BUILD_EXEEXT) ++ + # trigtables.c + trigtables.c: gentrigtables$(BUILD_EXEEXT) gentrigtables.c $(top_srcdir)/configure.ac + ./gentrigtables$(BUILD_EXEEXT) > $@ +@@ -387,7 +391,7 @@ moddep.lst: syminfo.lst genmoddep.awk video.lst + platform_DATA += moddep.lst + CLEANFILES += config.log syminfo.lst moddep.lst + +-$(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT) ++$(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT) build-grub-module-verifier + TARGET_OBJ2ELF=@TARGET_OBJ2ELF@ sh $^ $@ + platform_DATA += $(MOD_FILES) + platform_DATA += modinfo.sh +diff --git a/grub-core/genmod.sh.in b/grub-core/genmod.sh.in +index 789732b108b..7dcafd9d370 100644 +--- a/grub-core/genmod.sh.in ++++ b/grub-core/genmod.sh.in +@@ -15,12 +15,12 @@ set -e + # + # Example: + # +-# genmod.sh moddep.lst normal.module normal.mod ++# genmod.sh moddep.lst normal.module build-grub-module-verifier normal.mod + # + + moddep=$1 + infile=$2 +-outfile=$3 ++outfile=$4 + + tmpfile=${outfile}.tmp + modname=`echo $infile | sed -e 's@\.module.*$@@'` +@@ -93,4 +93,5 @@ else + -wd1106 -nu -nd $tmpfile.bin $tmpfile || exit 1 + rm -f $name.bin + fi ++./build-grub-module-verifier $tmpfile @target_cpu@ + mv $tmpfile $outfile diff --git a/SOURCES/0273-module-verifier-Check-range-limited-relative-relocat.patch b/SOURCES/0273-module-verifier-Check-range-limited-relative-relocat.patch new file mode 100644 index 0000000..9d23811 --- /dev/null +++ b/SOURCES/0273-module-verifier-Check-range-limited-relative-relocat.patch @@ -0,0 +1,183 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Thu, 31 Dec 2015 15:29:28 +0100 +Subject: [PATCH] module-verifier: Check range-limited relative relocations. + +Check that they point to the same module, so will end up in the same +chunk of memory. +--- + util/grub-module-verifier.c | 19 ++++++++++--- + util/grub-module-verifierXX.c | 62 ++++++++++++++++++++++++++++++++++-------- + include/grub/module_verifier.h | 1 + + 3 files changed, 67 insertions(+), 15 deletions(-) + +diff --git a/util/grub-module-verifier.c b/util/grub-module-verifier.c +index d2d6984033c..c027f0a0fb1 100644 +--- a/util/grub-module-verifier.c ++++ b/util/grub-module-verifier.c +@@ -15,9 +15,13 @@ struct grub_module_verifier_arch archs[] = { + { "x86_64", 8, 0, EM_X86_64, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){ + R_X86_64_64, + R_X86_64_PC64, +- /* R_X86_64_32, R_X86_64_32S, R_X86_64_PC32 are supported but shouldn't be used because of their limited range. */ ++ /* R_X86_64_32, R_X86_64_32S are supported but shouldn't be used because of their limited range. */ + -1 +- } }, ++ }, (int[]){ ++ R_X86_64_PC32, ++ -1 ++ } ++ }, + { "powerpc", 4, 1, EM_PPC, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){ + GRUB_ELF_R_PPC_ADDR16_LO, + GRUB_ELF_R_PPC_REL24, /* It has limited range but GRUB adds trampolines when necessarry. */ +@@ -39,17 +43,24 @@ struct grub_module_verifier_arch archs[] = { + } }, + { "ia64", 8, 0, EM_IA_64, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){ + R_IA64_PCREL21B, /* We should verify that it's pointing either +- to a function or to a section in the same module. */ ++ to a function or to a section in the same module. ++ Checking that external symbol is a function is ++ non-trivial and I have never seen this relocation used ++ for anything else, so assume that it always points to a ++ function. ++ */ + R_IA64_SEGREL64LSB, + R_IA64_FPTR64LSB, + R_IA64_DIR64LSB, + R_IA64_PCREL64LSB, +- R_IA64_GPREL22, /* We should verify that it's pointing to a section in the same module. */ + R_IA64_LTOFF22X, + R_IA64_LTOFF22, + R_IA64_LTOFF_FPTR22, + R_IA64_LDXMOV, + -1 ++ }, (int[]){ ++ R_IA64_GPREL22, ++ -1 + } }, + { "mipsel", 4, 0, EM_MIPS, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){ + R_MIPS_HI16, +diff --git a/util/grub-module-verifierXX.c b/util/grub-module-verifierXX.c +index 904be27d39b..25988ebc21d 100644 +--- a/util/grub-module-verifierXX.c ++++ b/util/grub-module-verifierXX.c +@@ -161,14 +161,12 @@ check_license (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e) + grub_util_error ("incompatible license"); + } + +-static void +-check_symbols (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e) ++static Elf_Sym * ++get_symtab (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e, Elf_Word *size, Elf_Word *entsize) + { + unsigned i; + Elf_Shdr *s, *sections; + Elf_Sym *sym; +- const char *str; +- Elf_Word size, entsize; + + sections = (Elf_Shdr *) ((char *) e + grub_target_to_host (e->e_shoff)); + for (i = 0, s = sections; +@@ -181,11 +179,19 @@ check_symbols (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e) + grub_util_error ("no symbol table"); + + sym = (Elf_Sym *) ((char *) e + grub_target_to_host (s->sh_offset)); +- size = grub_target_to_host (s->sh_size); +- entsize = grub_target_to_host (s->sh_entsize); ++ *size = grub_target_to_host (s->sh_size); ++ *entsize = grub_target_to_host (s->sh_entsize); ++ return sym; ++} + +- s = (Elf_Shdr *) ((char *) sections + grub_target_to_host16 (e->e_shentsize) * grub_target_to_host32 (s->sh_link)); +- str = (char *) e + grub_target_to_host (s->sh_offset); ++static void ++check_symbols (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e) ++{ ++ Elf_Sym *sym; ++ Elf_Word size, entsize; ++ unsigned i; ++ ++ sym = get_symtab (arch, e, &size, &entsize); + + for (i = 0; + i < size / entsize; +@@ -208,19 +214,41 @@ check_symbols (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e) + } + } + +-/* Relocate symbols. */ ++static int ++is_symbol_local(Elf_Sym *sym) ++{ ++ switch (ELF_ST_TYPE (sym->st_info)) ++ { ++ case STT_NOTYPE: ++ case STT_OBJECT: ++ if (sym->st_name != 0 && sym->st_shndx == 0) ++ return 0; ++ return 1; ++ ++ case STT_FUNC: ++ case STT_SECTION: ++ return 1; ++ ++ default: ++ return 0; ++ } ++} ++ + static void + section_check_relocations (const struct grub_module_verifier_arch *arch, void *ehdr, + Elf_Shdr *s, size_t target_seg_size) + { + Elf_Rel *rel, *max; ++ Elf_Sym *symtab; ++ Elf_Word symtabsize, symtabentsize; ++ ++ symtab = get_symtab (arch, ehdr, &symtabsize, &symtabentsize); + + for (rel = (Elf_Rel *) ((char *) ehdr + grub_target_to_host (s->sh_offset)), + max = (Elf_Rel *) ((char *) rel + grub_target_to_host (s->sh_size)); + rel < max; + rel = (Elf_Rel *) ((char *) rel + grub_target_to_host (s->sh_entsize))) + { +- Elf_Word *addr; + Elf_Sym *sym; + unsigned i; + +@@ -235,8 +263,20 @@ section_check_relocations (const struct grub_module_verifier_arch *arch, void *e + for (i = 0; arch->supported_relocations[i] != -1; i++) + if (type == arch->supported_relocations[i]) + break; +- if (arch->supported_relocations[i] == -1) ++ if (arch->supported_relocations[i] != -1) ++ continue; ++ if (!arch->short_relocations) + grub_util_error ("unsupported relocation 0x%x", type); ++ for (i = 0; arch->short_relocations[i] != -1; i++) ++ if (type == arch->short_relocations[i]) ++ break; ++ if (arch->short_relocations[i] == -1) ++ grub_util_error ("unsupported relocation 0x%x", type); ++ sym = (Elf_Sym *) ((char *) symtab + symtabentsize * ELF_R_SYM (grub_target_to_host (rel->r_info))); ++ ++ if (is_symbol_local (sym)) ++ continue; ++ grub_util_error ("relocation 0x%x is not module-local", type); + } + } + +diff --git a/include/grub/module_verifier.h b/include/grub/module_verifier.h +index 9e3a2ba720f..6cddff30f2e 100644 +--- a/include/grub/module_verifier.h ++++ b/include/grub/module_verifier.h +@@ -13,6 +13,7 @@ struct grub_module_verifier_arch { + int machine; + int flags; + const int *supported_relocations; ++ const int *short_relocations; + }; + + void grub_module_verify64(void *module_img, size_t module_size, const struct grub_module_verifier_arch *arch); diff --git a/SOURCES/0274-Strip-.ARM.exidx.patch b/SOURCES/0274-Strip-.ARM.exidx.patch new file mode 100644 index 0000000..aed2f16 --- /dev/null +++ b/SOURCES/0274-Strip-.ARM.exidx.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Thu, 31 Dec 2015 18:13:59 +0100 +Subject: [PATCH] Strip .ARM.exidx + +This section is generated by clang and is useful only for debugging. +It contains exotic relocations, so strip them to avoid them interferring +with module loading. +--- + gentpl.py | 2 +- + grub-core/genmod.sh.in | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/gentpl.py b/gentpl.py +index 889cc91d39c..58430fcd236 100644 +--- a/gentpl.py ++++ b/gentpl.py +@@ -753,7 +753,7 @@ def image(defn, platform): + if test x$(TARGET_APPLE_LINKER) = x1; then \ + $(MACHO2IMG) $< $@; \ + else \ +- $(TARGET_OBJCOPY) $(""" + cname(defn) + """_OBJCOPYFLAGS) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn -R .note.gnu.gold-version $< $@; \ ++ $(TARGET_OBJCOPY) $(""" + cname(defn) + """_OBJCOPYFLAGS) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .MIPS.abiflags -R .reginfo -R .rel.dyn -R .note.gnu.gold-version -R .ARM.exidx $< $@; \ + fi + """) + +diff --git a/grub-core/genmod.sh.in b/grub-core/genmod.sh.in +index 7dcafd9d370..005cb198504 100644 +--- a/grub-core/genmod.sh.in ++++ b/grub-core/genmod.sh.in +@@ -58,7 +58,7 @@ if test x@TARGET_APPLE_LINKER@ != x1; then + -K grub_mod_init -K grub_mod_fini \ + -K _grub_mod_init -K _grub_mod_fini \ + -R .note.gnu.gold-version -R .note.GNU-stack \ +- -R .note -R .comment $tmpfile || exit 1 ++ -R .note -R .comment -R .ARM.exidx $tmpfile || exit 1 + fi + if ! test -z "${TARGET_OBJ2ELF}"; then + "${TARGET_OBJ2ELF}" $tmpfile || exit 1 diff --git a/SOURCES/0275-Disable-build-time-module-check-on-emu.patch b/SOURCES/0275-Disable-build-time-module-check-on-emu.patch new file mode 100644 index 0000000..51c4d4e --- /dev/null +++ b/SOURCES/0275-Disable-build-time-module-check-on-emu.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Thu, 31 Dec 2015 18:20:11 +0100 +Subject: [PATCH] Disable build-time module check on emu. + +On emu some checks can be laxer like check for relocation range. Additionally +module loading in emu is rarely used. So skip this check rather than making +it laxer for all platforms. In ideal we may want to have slightly different +check for emu but for now this is good enough. +--- + grub-core/genmod.sh.in | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/grub-core/genmod.sh.in b/grub-core/genmod.sh.in +index 005cb198504..f74edd55181 100644 +--- a/grub-core/genmod.sh.in ++++ b/grub-core/genmod.sh.in +@@ -93,5 +93,7 @@ else + -wd1106 -nu -nd $tmpfile.bin $tmpfile || exit 1 + rm -f $name.bin + fi +-./build-grub-module-verifier $tmpfile @target_cpu@ ++if test x@platform@ != xemu; then ++ ./build-grub-module-verifier $tmpfile @target_cpu@ ++fi + mv $tmpfile $outfile diff --git a/SOURCES/0276-module-verifier-allow-limited-range-relocations-on-s.patch b/SOURCES/0276-module-verifier-allow-limited-range-relocations-on-s.patch new file mode 100644 index 0000000..c1791b3 --- /dev/null +++ b/SOURCES/0276-module-verifier-allow-limited-range-relocations-on-s.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Thu, 31 Dec 2015 18:30:39 +0100 +Subject: [PATCH] module-verifier: allow limited-range relocations on sparc64. + +clang as incomplete mcmodel=large support. As we don't currently need full +mcmodel=large support for sparc64, relax those checks. +--- + util/grub-module-verifier.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/util/grub-module-verifier.c b/util/grub-module-verifier.c +index c027f0a0fb1..e217dcddc07 100644 +--- a/util/grub-module-verifier.c ++++ b/util/grub-module-verifier.c +@@ -38,7 +38,12 @@ struct grub_module_verifier_arch archs[] = { + R_SPARC_LO10, + R_SPARC_64, + R_SPARC_OLO10, +- /* R_SPARC_32, R_SPARC_HI22 are supported but shouldn't be used because of their limited range. */ ++ /* Following 2 relocations have limited range but unfortunately ++ clang generates them, as it doesn't implement mcmodel=large properly. ++ At least our heap and core are under 4G, so it's not a problem ++ usually. */ ++ R_SPARC_HI22, ++ R_SPARC_32, + -1 + } }, + { "ia64", 8, 0, EM_IA_64, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){ diff --git a/SOURCES/0277-remove-temporary-.bin-files-kernel-and-modules.patch b/SOURCES/0277-remove-temporary-.bin-files-kernel-and-modules.patch new file mode 100644 index 0000000..632f137 --- /dev/null +++ b/SOURCES/0277-remove-temporary-.bin-files-kernel-and-modules.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrey Borzenkov +Date: Thu, 31 Dec 2015 23:00:25 +0300 +Subject: [PATCH] remove temporary .bin files (kernel and modules) + +--- + gentpl.py | 2 ++ + grub-core/genmod.sh.in | 2 +- + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/gentpl.py b/gentpl.py +index 58430fcd236..c17a18b0ea0 100644 +--- a/gentpl.py ++++ b/gentpl.py +@@ -723,9 +723,11 @@ def kernel(defn, platform): + """if test x$(TARGET_APPLE_LINKER) = x1; then \ + $(TARGET_STRIP) -S -x $(""" + cname(defn) + """) -o $@.bin $<; \ + $(TARGET_OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -ed2022 -ed2016 -wd1106 -nu -nd $@.bin $@; \ ++ rm -f $@.bin; \ + elif test ! -z '$(TARGET_OBJ2ELF)'; then \ + """ + "$(TARGET_STRIP) $(" + cname(defn) + "_STRIPFLAGS) -o $@.bin $< && \ + $(TARGET_OBJ2ELF) $@.bin $@ || (rm -f $@; rm -f $@.bin; exit 1); \ ++ rm -f $@.bin; \ + else """ + "$(TARGET_STRIP) $(" + cname(defn) + "_STRIPFLAGS) -o $@ $<; \ + fi""")) + +diff --git a/grub-core/genmod.sh.in b/grub-core/genmod.sh.in +index f74edd55181..ca2e59d5c42 100644 +--- a/grub-core/genmod.sh.in ++++ b/grub-core/genmod.sh.in +@@ -91,7 +91,7 @@ else + -nr:_grub_mod_init:grub_mod_init \ + -nr:_grub_mod_fini:grub_mod_fini \ + -wd1106 -nu -nd $tmpfile.bin $tmpfile || exit 1 +- rm -f $name.bin ++ rm -f $tmpfile.bin + fi + if test x@platform@ != xemu; then + ./build-grub-module-verifier $tmpfile @target_cpu@ diff --git a/SOURCES/0278-Add-missing-BUILD_EXEEXT.patch b/SOURCES/0278-Add-missing-BUILD_EXEEXT.patch new file mode 100644 index 0000000..afcd89c --- /dev/null +++ b/SOURCES/0278-Add-missing-BUILD_EXEEXT.patch @@ -0,0 +1,111 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Fri, 1 Jan 2016 11:13:54 +0300 +Subject: [PATCH] Add missing BUILD_EXEEXT + +--- + Makefile.am | 45 +++++++++++++++++++++++++-------------------- + grub-core/Makefile.am | 2 +- + grub-core/genmod.sh.in | 2 +- + 3 files changed, 27 insertions(+), 22 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index f02ae0a393c..335a268ea9f 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -85,16 +85,21 @@ CLEANFILES += build-grub-gen-widthspec$(BUILD_EXEEXT) + + if COND_STARFIELD + starfield_DATA = dejavu_10.pf2 dejavu_12.pf2 dejavu_bold_14.pf2 dejavu_14.pf2 dejavu_16.pf2 $(starfield_theme_files) +-dejavu_10.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont +- ./build-grub-mkfont -s 10 -o $@ $(DJVU_FONT_SOURCE) +-dejavu_12.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont +- ./build-grub-mkfont -s 12 -o $@ $(DJVU_FONT_SOURCE) +-dejavu_14.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont +- ./build-grub-mkfont -s 14 -o $@ $(DJVU_FONT_SOURCE) +-dejavu_bold_14.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont +- ./build-grub-mkfont -b -s 14 -o $@ $(DJVU_FONT_SOURCE) +-dejavu_16.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont +- ./build-grub-mkfont -s 16 -o $@ $(DJVU_FONT_SOURCE) ++dejavu_10.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT) ++ ./build-grub-mkfont$(BUILD_EXEEXT) -s 10 -o $@ $(DJVU_FONT_SOURCE) ++CLEANFILES += dejavu_10.pf2 ++dejavu_12.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT) ++ ./build-grub-mkfont$(BUILD_EXEEXT) -s 12 -o $@ $(DJVU_FONT_SOURCE) ++CLEANFILES += dejavu_12.pf2 ++dejavu_14.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT) ++ ./build-grub-mkfont$(BUILD_EXEEXT) -s 14 -o $@ $(DJVU_FONT_SOURCE) ++CLEANFILES += dejavu_14.pf2 ++dejavu_bold_14.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT) ++ ./build-grub-mkfont$(BUILD_EXEEXT) -b -s 14 -o $@ $(DJVU_FONT_SOURCE) ++CLEANFILES += dejavu_bold_14.pf2 ++dejavu_16.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT) ++ ./build-grub-mkfont$(BUILD_EXEEXT) -s 16 -o $@ $(DJVU_FONT_SOURCE) ++CLEANFILES += dejavu_16.pf2 + else + starfield_DATA = + endif +@@ -102,28 +107,28 @@ endif + EXTRA_DIST += $(starfield_theme_files) + EXTRA_DIST += $(srcdir)/themes/starfield/src/slider_s.xcf $(srcdir)/themes/starfield/src/slider_n.xcf $(srcdir)/themes/starfield/src/slider_c.xcf $(srcdir)/themes/starfield/src/blob_nw.xcf $(srcdir)/themes/starfield/src/bootmenu/center.xcf $(srcdir)/themes/starfield/src/bootmenu/corner.xcf $(srcdir)/themes/starfield/src/bootmenu/side.xcf $(srcdir)/themes/starfield/src/terminalbox/side.xcf $(srcdir)/themes/starfield/src/terminalbox/corner.xcf $(srcdir)/themes/starfield/src/terminalbox/center.xcf + +-unicode.pf2: $(FONT_SOURCE) build-grub-mkfont +- ./build-grub-mkfont -o $@ $(FONT_SOURCE) || (rm -f $@; exit 1) ++unicode.pf2: $(FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT) ++ ./build-grub-mkfont$(BUILD_EXEEXT) -o $@ $(FONT_SOURCE) || (rm -f $@; exit 1) + CLEANFILES += unicode.pf2 + + # Arrows and lines are needed to draw the menu, so always include them + UNICODE_ARROWS=0x2190-0x2193 + UNICODE_LINES=0x2501-0x251B + +-ascii.pf2: $(FONT_SOURCE) build-grub-mkfont +- ./build-grub-mkfont -o $@ $(FONT_SOURCE) -r 0x0-0x7f,$(UNICODE_ARROWS),$(UNICODE_LINES) || (rm -f $@; exit 1) ++ascii.pf2: $(FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT) ++ ./build-grub-mkfont$(BUILD_EXEEXT) -o $@ $(FONT_SOURCE) -r 0x0-0x7f,$(UNICODE_ARROWS),$(UNICODE_LINES) || (rm -f $@; exit 1) + CLEANFILES += ascii.pf2 + +-euro.pf2: $(FONT_SOURCE) build-grub-mkfont +- ./build-grub-mkfont -o $@ $(FONT_SOURCE) -r 0x0-0x4ff,0x1e00-0x1fff,$(UNICODE_ARROWS),$(UNICODE_LINES) || (rm -f $@; exit 1) ++euro.pf2: $(FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT) ++ ./build-grub-mkfont$(BUILD_EXEEXT) -o $@ $(FONT_SOURCE) -r 0x0-0x4ff,0x1e00-0x1fff,$(UNICODE_ARROWS),$(UNICODE_LINES) || (rm -f $@; exit 1) + CLEANFILES += euro.pf2 + +-ascii.h: $(FONT_SOURCE) build-grub-gen-asciih +- ./build-grub-gen-asciih $(FONT_SOURCE) $@ || (rm -f $@; exit 1) ++ascii.h: $(FONT_SOURCE) build-grub-gen-asciih$(BUILD_EXEEXT) ++ ./build-grub-gen-asciih$(BUILD_EXEEXT) $(FONT_SOURCE) $@ || (rm -f $@; exit 1) + CLEANFILES += ascii.h + +-widthspec.h: $(FONT_SOURCE) build-grub-gen-widthspec +- ./build-grub-gen-widthspec $(FONT_SOURCE) $@ || (rm -f $@; exit 1) ++widthspec.h: $(FONT_SOURCE) build-grub-gen-widthspec$(BUILD_EXEEXT) ++ ./build-grub-gen-widthspec$(BUILD_EXEEXT) $(FONT_SOURCE) $@ || (rm -f $@; exit 1) + CLEANFILES += widthspec.h + + # Install config.h into platformdir +diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am +index 77205f16358..59a00f11fab 100644 +--- a/grub-core/Makefile.am ++++ b/grub-core/Makefile.am +@@ -391,7 +391,7 @@ moddep.lst: syminfo.lst genmoddep.awk video.lst + platform_DATA += moddep.lst + CLEANFILES += config.log syminfo.lst moddep.lst + +-$(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT) build-grub-module-verifier ++$(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT) build-grub-module-verifier$(BUILD_EXEEXT) + TARGET_OBJ2ELF=@TARGET_OBJ2ELF@ sh $^ $@ + platform_DATA += $(MOD_FILES) + platform_DATA += modinfo.sh +diff --git a/grub-core/genmod.sh.in b/grub-core/genmod.sh.in +index ca2e59d5c42..045817b1534 100644 +--- a/grub-core/genmod.sh.in ++++ b/grub-core/genmod.sh.in +@@ -94,6 +94,6 @@ else + rm -f $tmpfile.bin + fi + if test x@platform@ != xemu; then +- ./build-grub-module-verifier $tmpfile @target_cpu@ ++ ./build-grub-module-verifier@BUILD_EXEEXT@ $tmpfile @target_cpu@ + fi + mv $tmpfile $outfile diff --git a/SOURCES/0279-grub-module-verifier-fix-unintended-sign-extension.patch b/SOURCES/0279-grub-module-verifier-fix-unintended-sign-extension.patch new file mode 100644 index 0000000..3284408 --- /dev/null +++ b/SOURCES/0279-grub-module-verifier-fix-unintended-sign-extension.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Fri, 8 Jan 2016 11:05:16 +0300 +Subject: [PATCH] grub-module-verifier: fix unintended sign extension + +Found by: Coverity scan. +CID: 156533, 156532 +--- + util/grub-module-verifierXX.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/util/grub-module-verifierXX.c b/util/grub-module-verifierXX.c +index 25988ebc21d..f612d51f389 100644 +--- a/util/grub-module-verifierXX.c ++++ b/util/grub-module-verifierXX.c +@@ -337,7 +337,7 @@ SUFFIX(grub_module_verify) (void *module_img, size_t size, const struct grub_mod + + /* Make sure that every section is within the core. */ + if (size < grub_target_to_host (e->e_shoff) +- + grub_target_to_host16 (e->e_shentsize) * grub_target_to_host16(e->e_shnum)) ++ + (grub_uint32_t) grub_target_to_host16 (e->e_shentsize) * grub_target_to_host16(e->e_shnum)) + { + grub_util_error ("ELF sections outside core"); + } diff --git a/SOURCES/0280-mkimage-fix-unintended-sign-extension.patch b/SOURCES/0280-mkimage-fix-unintended-sign-extension.patch new file mode 100644 index 0000000..f151b7f --- /dev/null +++ b/SOURCES/0280-mkimage-fix-unintended-sign-extension.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Sat, 9 Jan 2016 21:05:44 +0300 +Subject: [PATCH] mkimage: fix unintended sign extension + +Found by: Coverity scan. +CID: 73691, 73717 +--- + util/grub-mkimagexx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c +index 0a1ac9e517c..66e8576411e 100644 +--- a/util/grub-mkimagexx.c ++++ b/util/grub-mkimagexx.c +@@ -1465,7 +1465,7 @@ SUFFIX (load_image) (const char *kernel_path, size_t *exec_size, + section_entsize = grub_target_to_host16 (e->e_shentsize); + num_sections = grub_target_to_host16 (e->e_shnum); + +- if (kernel_size < section_offset + section_entsize * num_sections) ++ if (kernel_size < section_offset + (grub_uint32_t) section_entsize * num_sections) + grub_util_error (_("premature end of file %s"), kernel_path); + + sections = (Elf_Shdr *) (kernel_img + section_offset); diff --git a/SOURCES/0281-arm64-Add-support-for-relocations-needed-for-linaro-.patch b/SOURCES/0281-arm64-Add-support-for-relocations-needed-for-linaro-.patch new file mode 100644 index 0000000..030ecc7 --- /dev/null +++ b/SOURCES/0281-arm64-Add-support-for-relocations-needed-for-linaro-.patch @@ -0,0 +1,212 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Fri, 22 Jan 2016 19:09:37 +0100 +Subject: [PATCH] arm64: Add support for relocations needed for linaro gcc + +--- + grub-core/kern/arm64/dl.c | 18 ++++++++++++++++++ + grub-core/kern/arm64/dl_helper.c | 40 ++++++++++++++++++++++++++++++++++++++++ + util/grub-mkimagexx.c | 31 +++++++++++++++++++++++++++++++ + util/grub-module-verifier.c | 8 +++++++- + include/grub/arm64/reloc.h | 8 ++++++++ + include/grub/elf.h | 3 +++ + 6 files changed, 107 insertions(+), 1 deletion(-) + +diff --git a/grub-core/kern/arm64/dl.c b/grub-core/kern/arm64/dl.c +index e19ba6a0d58..cf50d7250d9 100644 +--- a/grub-core/kern/arm64/dl.c ++++ b/grub-core/kern/arm64/dl.c +@@ -132,6 +132,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + *abs_place = (grub_uint64_t) sym_addr; + } + break; ++ case R_AARCH64_ADD_ABS_LO12_NC: ++ grub_arm64_set_abs_lo12 (place, sym_addr); ++ break; ++ case R_AARCH64_LDST64_ABS_LO12_NC: ++ grub_arm64_set_abs_lo12_ldst64 (place, sym_addr); ++ break; + case R_AARCH64_CALL26: + case R_AARCH64_JUMP26: + { +@@ -154,6 +160,18 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + grub_arm64_set_xxxx26_offset (place, offset); + } + break; ++ case R_AARCH64_ADR_PREL_PG_HI21: ++ { ++ grub_int64_t offset = (sym_addr & ~0xfffULL) - (((grub_uint64_t) place) & ~0xfffULL); ++ ++ if (!grub_arm64_check_hi21_signed (offset)) ++ return grub_error (GRUB_ERR_BAD_MODULE, ++ "HI21 out of range"); ++ ++ grub_arm64_set_hi21 (place, offset); ++ } ++ break; ++ + default: + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("relocation 0x%x is not implemented yet"), +diff --git a/grub-core/kern/arm64/dl_helper.c b/grub-core/kern/arm64/dl_helper.c +index d213ab93e88..f031b1ae921 100644 +--- a/grub-core/kern/arm64/dl_helper.c ++++ b/grub-core/kern/arm64/dl_helper.c +@@ -53,3 +53,43 @@ grub_arm64_set_xxxx26_offset (grub_uint32_t *place, grub_int64_t offset) + *place &= insmask; + *place |= grub_cpu_to_le32 (offset >> 2) & ~insmask; + } ++ ++int ++grub_arm64_check_hi21_signed (grub_int64_t offset) ++{ ++ if (offset != (grub_int64_t)(grub_int32_t)offset) ++ return 0; ++ return 1; ++} ++ ++void ++grub_arm64_set_hi21 (grub_uint32_t *place, grub_int64_t offset) ++{ ++ const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0x9f00001f); ++ grub_uint32_t val; ++ ++ offset >>= 12; ++ ++ val = ((offset & 3) << 29) | (((offset >> 2) & 0x7ffff) << 5); ++ ++ *place &= insmask; ++ *place |= grub_cpu_to_le32 (val) & ~insmask; ++} ++ ++void ++grub_arm64_set_abs_lo12 (grub_uint32_t *place, grub_int64_t target) ++{ ++ const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xffc003ff); ++ ++ *place &= insmask; ++ *place |= grub_cpu_to_le32 (target << 10) & ~insmask; ++} ++ ++void ++grub_arm64_set_abs_lo12_ldst64 (grub_uint32_t *place, grub_int64_t target) ++{ ++ const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xfff803ff); ++ ++ *place &= insmask; ++ *place |= grub_cpu_to_le32 (target << 7) & ~insmask; ++} +diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c +index 66e8576411e..d1bc95e350d 100644 +--- a/util/grub-mkimagexx.c ++++ b/util/grub-mkimagexx.c +@@ -836,6 +836,14 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections, + *target = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr); + } + break; ++ case R_AARCH64_ADD_ABS_LO12_NC: ++ grub_arm64_set_abs_lo12 ((grub_uint32_t *) target, ++ sym_addr); ++ break; ++ case R_AARCH64_LDST64_ABS_LO12_NC: ++ grub_arm64_set_abs_lo12_ldst64 ((grub_uint32_t *) target, ++ sym_addr); ++ break; + case R_AARCH64_JUMP26: + case R_AARCH64_CALL26: + { +@@ -848,6 +856,17 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections, + sym_addr); + } + break; ++ case R_AARCH64_ADR_PREL_PG_HI21: ++ { ++ sym_addr &= ~0xfffULL; ++ sym_addr -= (offset + SUFFIX (entry_point)) & ~0xfffULL; ++ if (!grub_arm64_check_hi21_signed (sym_addr)) ++ grub_util_error ("%s", "CALL26 Relocation out of range"); ++ ++ grub_arm64_set_hi21((grub_uint32_t *)target, ++ sym_addr); ++ } ++ break; + default: + grub_util_error (_("relocation 0x%x is not implemented yet"), + (unsigned int) ELF_R_TYPE (info)); +@@ -1200,6 +1219,15 @@ SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out, + case R_AARCH64_CALL26: + case R_AARCH64_JUMP26: + break; ++ /* Page-relative relocations do not require fixup entries. */ ++ case R_AARCH64_ADR_PREL_PG_HI21: ++ /* We page-align the whole kernel, so no need ++ for fixup entries. ++ */ ++ case R_AARCH64_ADD_ABS_LO12_NC: ++ case R_AARCH64_LDST64_ABS_LO12_NC: ++ break; ++ + default: + grub_util_error (_("relocation 0x%x is not implemented yet"), + (unsigned int) ELF_R_TYPE (info)); +@@ -1343,6 +1371,9 @@ SUFFIX (locate_sections) (const char *kernel_path, + Elf_Shdr *s; + + *all_align = 1; ++ /* Page-aligning simplifies relocation handling. */ ++ if (image_target->elf_target == EM_AARCH64) ++ *all_align = 4096; + + section_addresses = xmalloc (sizeof (*section_addresses) * num_sections); + memset (section_addresses, 0, sizeof (*section_addresses) * num_sections); +diff --git a/util/grub-module-verifier.c b/util/grub-module-verifier.c +index e217dcddc07..405c9117051 100644 +--- a/util/grub-module-verifier.c ++++ b/util/grub-module-verifier.c +@@ -107,7 +107,13 @@ struct grub_module_verifier_arch archs[] = { + R_AARCH64_CALL26, + R_AARCH64_JUMP26, + -1 +- } }, ++ }, (int[]){ ++ R_AARCH64_ADR_PREL_PG_HI21, ++ R_AARCH64_ADD_ABS_LO12_NC, ++ R_AARCH64_LDST64_ABS_LO12_NC, ++ -1 ++ } ++ }, + }; + + +diff --git a/include/grub/arm64/reloc.h b/include/grub/arm64/reloc.h +index 4aed3d715e0..452c148226d 100644 +--- a/include/grub/arm64/reloc.h ++++ b/include/grub/arm64/reloc.h +@@ -22,5 +22,13 @@ + int grub_arm_64_check_xxxx26_offset (grub_int64_t offset); + void + grub_arm64_set_xxxx26_offset (grub_uint32_t *place, grub_int64_t offset); ++int ++grub_arm64_check_hi21_signed (grub_int64_t offset); ++void ++grub_arm64_set_hi21 (grub_uint32_t *place, grub_int64_t offset); ++void ++grub_arm64_set_abs_lo12 (grub_uint32_t *place, grub_int64_t target); ++void ++grub_arm64_set_abs_lo12_ldst64 (grub_uint32_t *place, grub_int64_t target); + + #endif +diff --git a/include/grub/elf.h b/include/grub/elf.h +index caa79639082..db15acecf9f 100644 +--- a/include/grub/elf.h ++++ b/include/grub/elf.h +@@ -2068,6 +2068,9 @@ typedef Elf32_Addr Elf32_Conflict; + #define R_AARCH64_NONE 0 /* No relocation. */ + #define R_AARCH64_ABS64 257 /* Direct 64 bit. */ + #define R_AARCH64_ABS32 258 /* Direct 32 bit. */ ++#define R_AARCH64_ADR_PREL_PG_HI21 275 ++#define R_AARCH64_ADD_ABS_LO12_NC 277 ++#define R_AARCH64_LDST64_ABS_LO12_NC 286 + #define R_AARCH64_JUMP26 282 /* 26-bit relative. */ + #define R_AARCH64_CALL26 283 /* 26-bit relative. */ + #define R_AARCH64_COPY 1024 /* Copy symbol at runtime. */ diff --git a/SOURCES/0282-support-modules-without-symbol-table.patch b/SOURCES/0282-support-modules-without-symbol-table.patch new file mode 100644 index 0000000..326deb6 --- /dev/null +++ b/SOURCES/0282-support-modules-without-symbol-table.patch @@ -0,0 +1,106 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Wed, 3 Feb 2016 20:34:55 +0300 +Subject: [PATCH] support modules without symbol table + +all_video module does not have any code or data and exists solely for +.moddeps section to pull in dependencies. This makes all symbols unneeded. + +While in current binutils (last released version as of this commit is 2.26) +``strip --strip-unneeded'' unintentionally adds section symbols for each +existing section, this behavior was considered a bug and changed in commit +14f2c699ddca1e2f706342dffc59a6c7e23e844c to completely strip symbol table +in this case. + +Older binutils (verified with 2.17) and some other toolchains (at least +elftoolchain r3223M), both used in FreeBSD, remove symbol table in all_video +as well. + +Relax run-time check and do not return error for modules without symbol table. +Add additional checks to module verifier to make sure such modules + +a) have non-empty .moddeps section. Without either externally visible symbols +or .moddeps modules are completely useless and should not be built. + +b) do not have any relocations. + +Closes: 46986 + +v2: add run-time check for empty symbol table if relocations are present as + suggested by Vladimir. +--- + grub-core/kern/dl.c | 8 +++++++- + util/grub-module-verifierXX.c | 18 +++++++++++++++++- + 2 files changed, 24 insertions(+), 2 deletions(-) + +diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c +index b0b0405fcbe..c45afc64950 100644 +--- a/grub-core/kern/dl.c ++++ b/grub-core/kern/dl.c +@@ -341,8 +341,11 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e) + if (s->sh_type == SHT_SYMTAB) + break; + ++ /* Module without symbol table may still be used to pull in dependencies. ++ We verify at build time that such modules do not contain any relocations ++ that may reference symbol table. */ + if (i == e->e_shnum) +- return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table")); ++ return GRUB_ERR_NONE; + + #ifdef GRUB_MODULES_MACHINE_READONLY + mod->symtab = grub_malloc (s->sh_size); +@@ -584,6 +587,9 @@ grub_dl_relocate_symbols (grub_dl_t mod, void *ehdr) + + if (seg) + { ++ if (!mod->symtab) ++ return grub_error (GRUB_ERR_BAD_MODULE, "relocation without symbol table"); ++ + err = grub_arch_dl_relocate_symbols (mod, ehdr, s, seg); + if (err) + return err; +diff --git a/util/grub-module-verifierXX.c b/util/grub-module-verifierXX.c +index f612d51f389..9c04caa63b4 100644 +--- a/util/grub-module-verifierXX.c ++++ b/util/grub-module-verifierXX.c +@@ -176,7 +176,7 @@ get_symtab (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e, Elf_Word + break; + + if (i == grub_target_to_host16 (e->e_shnum)) +- grub_util_error ("no symbol table"); ++ return NULL; + + sym = (Elf_Sym *) ((char *) e + grub_target_to_host (s->sh_offset)); + *size = grub_target_to_host (s->sh_size); +@@ -191,7 +191,21 @@ check_symbols (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e) + Elf_Word size, entsize; + unsigned i; + ++ /* Module without symbol table and without .moddeps section is useless ++ at boot time, so catch it early to prevent build errors */ + sym = get_symtab (arch, e, &size, &entsize); ++ if (!sym) ++ { ++ Elf_Shdr *s = find_section (arch, e, ".moddeps"); ++ ++ if (!s) ++ grub_util_error ("no symbol table and no .moddeps section"); ++ ++ if (!s->sh_size) ++ grub_util_error ("no symbol table and empty .moddeps section"); ++ ++ return; ++ } + + for (i = 0; + i < size / entsize; +@@ -243,6 +257,8 @@ section_check_relocations (const struct grub_module_verifier_arch *arch, void *e + Elf_Word symtabsize, symtabentsize; + + symtab = get_symtab (arch, ehdr, &symtabsize, &symtabentsize); ++ if (!symtab) ++ grub_util_error ("relocation without symbol table"); + + for (rel = (Elf_Rel *) ((char *) ehdr + grub_target_to_host (s->sh_offset)), + max = (Elf_Rel *) ((char *) rel + grub_target_to_host (s->sh_size)); diff --git a/SOURCES/0283-cacheinfo-Add-missing-license-information.patch b/SOURCES/0283-cacheinfo-Add-missing-license-information.patch new file mode 100644 index 0000000..fd6c6d6 --- /dev/null +++ b/SOURCES/0283-cacheinfo-Add-missing-license-information.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Vladimir Serbinenko +Date: Fri, 20 Mar 2015 11:13:58 +0100 +Subject: [PATCH] cacheinfo: Add missing license information. + +--- + grub-core/commands/cacheinfo.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/grub-core/commands/cacheinfo.c b/grub-core/commands/cacheinfo.c +index ead6ff82cfc..d34a346964c 100644 +--- a/grub-core/commands/cacheinfo.c ++++ b/grub-core/commands/cacheinfo.c +@@ -23,6 +23,8 @@ + #include + #include + ++GRUB_MOD_LICENSE ("GPLv3+"); ++ + static grub_err_t + grub_rescue_cmd_info (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), diff --git a/SOURCES/0284-arm64-setjmp-Add-missing-license-macro.patch b/SOURCES/0284-arm64-setjmp-Add-missing-license-macro.patch new file mode 100644 index 0000000..0424f79 --- /dev/null +++ b/SOURCES/0284-arm64-setjmp-Add-missing-license-macro.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: dann frazier +Date: Thu, 21 May 2015 10:28:48 -0600 +Subject: [PATCH] arm64/setjmp: Add missing license macro + +Including the setjmp module in an arm64-efi image will cause it to +immediately exit with an "incompatible license" error. + +The source file includes a GPLv3+ boilerplate, so fix this by declaring a +GPLv3+ license using the GRUB_MOD_LICENSE macro. + +Signed-off-by: dann frazier +--- + grub-core/lib/arm64/setjmp.S | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/grub-core/lib/arm64/setjmp.S b/grub-core/lib/arm64/setjmp.S +index adaafe40f71..eabfd99b296 100644 +--- a/grub-core/lib/arm64/setjmp.S ++++ b/grub-core/lib/arm64/setjmp.S +@@ -17,8 +17,10 @@ + */ + + #include ++#include + + .file "setjmp.S" ++GRUB_MOD_LICENSE "GPLv3+" + .text + + /* diff --git a/SOURCES/0285-editenv-handle-relative-symlinks.patch b/SOURCES/0285-editenv-handle-relative-symlinks.patch new file mode 100644 index 0000000..20e1686 --- /dev/null +++ b/SOURCES/0285-editenv-handle-relative-symlinks.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jonathan Lebon +Date: Mon, 14 Aug 2017 14:37:20 -0400 +Subject: [PATCH] editenv: handle relative symlinks + +Handle symlinks with targets relative to the containing dir. This +ensures that the rename operation does not depend on the cwd. + +Resolves: rhbz#1479960 + +Signed-off-by: Jonathan Lebon +--- + util/editenv.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/util/editenv.c b/util/editenv.c +index d8d1dad6ab9..41bc7cb1c9a 100644 +--- a/util/editenv.c ++++ b/util/editenv.c +@@ -28,6 +28,7 @@ + + #include + #include ++#include + + #define DEFAULT_ENVBLK_SIZE 1024 + +@@ -87,9 +88,20 @@ grub_util_create_envblk_file (const char *name) + continue; + } + +- free (rename_target); + linkbuf[retsize] = '\0'; +- rename_target = linkbuf; ++ if (linkbuf[0] == '/') ++ { ++ free (rename_target); ++ rename_target = linkbuf; ++ } ++ else ++ { ++ char *dbuf = xstrdup (rename_target); ++ const char *dir = dirname (dbuf); ++ free (rename_target); ++ rename_target = xasprintf("%s/%s", dir, linkbuf); ++ free (dbuf); ++ } + } + + int rc = grub_util_rename (namenew, rename_target); diff --git a/SOURCES/0286-efinet-also-use-the-firmware-acceleration-for-http.patch b/SOURCES/0286-efinet-also-use-the-firmware-acceleration-for-http.patch new file mode 100644 index 0000000..5771c8a --- /dev/null +++ b/SOURCES/0286-efinet-also-use-the-firmware-acceleration-for-http.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 30 Jul 2018 14:06:42 -0400 +Subject: [PATCH] efinet: also use the firmware acceleration for http + +Signed-off-by: Peter Jones +--- + grub-core/net/efi/net.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/grub-core/net/efi/net.c b/grub-core/net/efi/net.c +index 2bf15447fd5..f208d1b180c 100644 +--- a/grub-core/net/efi/net.c ++++ b/grub-core/net/efi/net.c +@@ -1324,7 +1324,9 @@ grub_efi_net_boot_from_https (void) + && (subtype == GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)) + { + grub_efi_uri_device_path_t *uri_dp = (grub_efi_uri_device_path_t *) dp; +- return (grub_strncmp ((const char*)uri_dp->uri, "https://", sizeof ("https://") - 1) == 0) ? 1 : 0; ++ grub_dprintf ("efinet", "url:%s\n", (const char *)uri_dp->uri); ++ return (grub_strncmp ((const char *)uri_dp->uri, "https://", sizeof ("https://") - 1) == 0 || ++ grub_strncmp ((const char *)uri_dp->uri, "http://", sizeof ("http://") - 1) == 0); + } + + if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp)) diff --git a/SOURCES/0287-Make-root_url-reflect-the-protocol-hostname-of-our-b.patch b/SOURCES/0287-Make-root_url-reflect-the-protocol-hostname-of-our-b.patch new file mode 100644 index 0000000..2a5ffcd --- /dev/null +++ b/SOURCES/0287-Make-root_url-reflect-the-protocol-hostname-of-our-b.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 30 Jul 2018 16:39:57 -0400 +Subject: [PATCH] Make root_url reflect the protocol+hostname of our boot url. + +Signed-off-by: Peter Jones +--- + grub-core/net/efi/http.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/grub-core/net/efi/http.c b/grub-core/net/efi/http.c +index 3f61fd2fa5b..243acbaa35b 100644 +--- a/grub-core/net/efi/http.c ++++ b/grub-core/net/efi/http.c +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include + + static void + http_configure (struct grub_efi_net_device *dev, int prefer_ip6) +@@ -351,6 +352,24 @@ grub_efihttp_open (struct grub_efi_net_device *dev, + grub_err_t err; + grub_off_t size; + char *buf; ++ char *root_url; ++ grub_efi_ipv6_address_t address; ++ const char *rest; ++ ++ if (grub_efi_string_to_ip6_address (file->device->net->server, &address, &rest) && *rest == 0) ++ root_url = grub_xasprintf ("%s://[%s]", type ? "https" : "http", file->device->net->server); ++ else ++ root_url = grub_xasprintf ("%s://%s", type ? "https" : "http", file->device->net->server); ++ if (root_url) ++ { ++ grub_env_unset ("root_url"); ++ grub_env_set ("root_url", root_url); ++ grub_free (root_url); ++ } ++ else ++ { ++ return grub_errno; ++ } + + err = efihttp_request (dev->http, file->device->net->server, file->device->net->name, type, 1, 0); + if (err != GRUB_ERR_NONE) diff --git a/SOURCES/0288-efi-uga-Fix-PCIe-LER-when-GRUB2-accesses-non-enabled.patch b/SOURCES/0288-efi-uga-Fix-PCIe-LER-when-GRUB2-accesses-non-enabled.patch new file mode 100644 index 0000000..7101637 --- /dev/null +++ b/SOURCES/0288-efi-uga-Fix-PCIe-LER-when-GRUB2-accesses-non-enabled.patch @@ -0,0 +1,50 @@ +From a897321d9c318c18c92c6431115fd9be71fedba1 Mon Sep 17 00:00:00 2001 +From: "mike.travis@hpe.com" +Date: Wed, 28 Mar 2018 11:42:18 -0500 +Subject: [PATCH 288/288] efi/uga: Fix PCIe LER when GRUB2 accesses non-enabled + MMIO data from VGA + +A GPU inserted into a PCIe I/O slot disappears during system startup. +The problem centers around GRUB and a specific VGA init function in +efi_uga.c. This causes an LER (Link Error Recorvery) because the MMIO +memory has not been enabled before attempting access. + +The fix is to add the same coding used in other VGA drivers, specifically +to add a check to insure that it is indeed a VGA controller. And then +enable the MMIO address space with the specific bits. + +Signed-off-by: Mike Travis +Reviewed-by: Daniel Kiper +--- + grub-core/video/efi_uga.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/grub-core/video/efi_uga.c b/grub-core/video/efi_uga.c +index 1d4091c5631..97a607c01a5 100644 +--- a/grub-core/video/efi_uga.c ++++ b/grub-core/video/efi_uga.c +@@ -94,10 +94,19 @@ static int + find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data) + { + struct find_framebuf_ctx *ctx = data; +- grub_pci_address_t addr; ++ grub_pci_address_t addr, rcaddr; ++ grub_uint32_t subclass; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); +- if (grub_pci_read (addr) >> 24 == 0x3) ++ subclass = (grub_pci_read (addr) >> 16) & 0xffff; ++ ++ if (subclass != GRUB_PCI_CLASS_SUBCLASS_VGA) ++ return 0; ++ ++ /* Enable MEM address spaces */ ++ rcaddr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); ++ grub_pci_write_word (rcaddr, grub_pci_read_word (rcaddr) | GRUB_PCI_COMMAND_MEM_ENABLED); ++ + { + int i; + +-- +2.17.1 + diff --git a/SOURCES/0289-efidisk-prevent-errors-from-diskfilter-scan-of-remov.patch b/SOURCES/0289-efidisk-prevent-errors-from-diskfilter-scan-of-remov.patch new file mode 100644 index 0000000..70abdb9 --- /dev/null +++ b/SOURCES/0289-efidisk-prevent-errors-from-diskfilter-scan-of-remov.patch @@ -0,0 +1,54 @@ +From 8f4dc1510c0f42a549b91c28eda74fe8a1e2a5d4 Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Fri, 26 Feb 2016 21:44:37 +0300 +Subject: [PATCH] efidisk: prevent errors from diskfilter scan of removable + drives + +Map EFI_NO_MEDIA to GRUB_ERR_OUT_OF_RANGE that is ignored by diskfilter. This +actually matches pretty close (we obviously attempt to read outside of media) +and avoids adding more error codes. + +This affects only internally initiated scans. If read/write from removable is +explicitly requested, we still return an error and text explanation is more +clear for user than generic error. + +Reported and tested by Andreas Loew +--- + grub-core/disk/efi/efidisk.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c +index f04f20b84ff..41adc1b0421 100644 +--- a/grub-core/disk/efi/efidisk.c ++++ b/grub-core/disk/efi/efidisk.c +@@ -575,9 +575,11 @@ grub_efidisk_read (struct grub_disk *disk, grub_disk_addr_t sector, + + status = grub_efidisk_readwrite (disk, sector, size, buf, 0); + +- if (status != GRUB_EFI_SUCCESS) ++ if (status == GRUB_EFI_NO_MEDIA) ++ return grub_error (GRUB_ERR_OUT_OF_RANGE, "no media in `%s'", disk->name); ++ else if (status != GRUB_EFI_SUCCESS) + return grub_error (GRUB_ERR_READ_ERROR, +- N_("failure reading sector 0x%llx from `%s'"), ++ "failure reading sector 0x%llx from `%s'", + (unsigned long long) sector, + disk->name); + +@@ -596,9 +598,11 @@ grub_efidisk_write (struct grub_disk *disk, grub_disk_addr_t sector, + + status = grub_efidisk_readwrite (disk, sector, size, (char *) buf, 1); + +- if (status != GRUB_EFI_SUCCESS) ++ if (status == GRUB_EFI_NO_MEDIA) ++ return grub_error (GRUB_ERR_OUT_OF_RANGE, "no media in `%s'", disk->name); ++ else if (status != GRUB_EFI_SUCCESS) + return grub_error (GRUB_ERR_WRITE_ERROR, +- N_("failure writing sector 0x%llx to `%s'"), ++ "failure writing sector 0x%llx to `%s'", + (unsigned long long) sector, disk->name); + + return GRUB_ERR_NONE; +-- +2.20.1 + diff --git a/SOURCES/gitignore b/SOURCES/gitignore new file mode 100644 index 0000000..f318bf1 --- /dev/null +++ b/SOURCES/gitignore @@ -0,0 +1,243 @@ +00_header +10_* +20_linux_xen +30_os-prober +40_custom +41_custom +*.1 +*.8 +aclocal.m4 +ahci_test +ascii.bitmaps +ascii.h +autom4te.cache +build-grub-gen-asciih +build-grub-gen-widthspec +build-grub-mkfont +cdboot_test +cmp_test +config.cache +config.guess +config.h +config-util.h +config-util.h.in +config.log +config.status +config.sub +configure +core_compress_test +DISTLIST +docs/*.info +docs/stamp-vti +docs/version.texi +ehci_test +example_grub_script_test +example_scripted_test +example_unit_test +*.exec +*.exec.exe +fddboot_test +genkernsyms.sh +gensymlist.sh +gentrigtables +gentrigtables.exe +gettext_strings_test +grub-bin2h +/grub-bios-setup +/grub-bios-setup.exe +grub_cmd_date +grub_cmd_echo +grub_cmd_regexp +grub_cmd_set_date +grub_cmd_sleep +/grub-editenv +/grub-editenv.exe +grub-emu +grub-emu-lite +grub-emu.exe +grub-emu-lite.exe +grub_emu_init.c +grub_emu_init.h +grub-fstest +grub-fstest.exe +grub_fstest_init.c +grub_fstest_init.h +grub_func_test +grub-install +grub-install.exe +grub-kbdcomp +grub-macho2img +/grub-menulst2cfg +/grub-menulst2cfg.exe +/grub-mk* +grub-mount +/grub-ofpathname +/grub-ofpathname.exe +grub-core/build-grub-pe2elf.exe +/grub-probe +/grub-probe.exe +grub_probe_init.c +grub_probe_init.h +/grub-reboot +grub_script_blanklines +grub_script_blockarg +grub_script_break +grub-script-check +grub-script-check.exe +grub_script_check_init.c +grub_script_check_init.h +grub_script_comments +grub_script_continue +grub_script_dollar +grub_script_echo1 +grub_script_echo_keywords +grub_script_escape_comma +grub_script_eval +grub_script_expansion +grub_script_final_semicolon +grub_script_for1 +grub_script_functions +grub_script_gettext +grub_script_if +grub_script_leading_whitespace +grub_script_no_commands +grub_script_not +grub_script_return +grub_script_setparams +grub_script_shift +grub_script_strcmp +grub_script_test +grub_script_vars1 +grub_script_while1 +grub_script.tab.c +grub_script.tab.h +grub_script.yy.c +grub_script.yy.h +grub-set-default +grub_setup_init.c +grub_setup_init.h +grub-shell +grub-shell-tester +grub-sparc64-setup +grub-sparc64-setup.exe +gzcompress_test +hddboot_test +help_test +*.img +*.image +*.image.exe +include/grub/cpu +include/grub/machine +install-sh +lib/libgcrypt-grub +libgrub_a_init.c +*.log +*.lst +lzocompress_test +*.marker +Makefile +*.mod +mod-*.c +missing +netboot_test +*.o +*.a +ohci_test +partmap_test +pata_test +*.pf2 +*.pp +po/*.mo +po/grub.pot +po/POTFILES +po/stamp-po +printf_test +priority_queue_unit_test +pseries_test +stamp-h +stamp-h1 +stamp-h.in +symlist.c +symlist.h +trigtables.c +*.trs +uhci_test +update-grub_lib +unidata.c +xzcompress_test +Makefile.in +GPATH +GRTAGS +GSYMS +GTAGS +compile +depcomp +mdate-sh +texinfo.tex +grub-core/lib/libgcrypt-grub +.deps +.deps-util +.deps-core +.dirstamp +Makefile.util.am +contrib +grub-core/bootinfo.txt +grub-core/Makefile.core.am +grub-core/Makefile.gcry.def +grub-core/contrib +grub-core/gdb_grub +grub-core/genmod.sh +grub-core/gensyminfo.sh +grub-core/gmodule.pl +grub-core/grub.chrp +grub-core/modinfo.sh +grub-core/*.module +grub-core/*.module.exe +grub-core/*.pp +util/bash-completion.d/grub +grub-core/gnulib/alloca.h +grub-core/gnulib/arg-nonnull.h +grub-core/gnulib/c++defs.h +grub-core/gnulib/charset.alias +grub-core/gnulib/configmake.h +grub-core/gnulib/float.h +grub-core/gnulib/getopt.h +grub-core/gnulib/langinfo.h +grub-core/gnulib/ref-add.sed +grub-core/gnulib/ref-del.sed +grub-core/gnulib/stdio.h +grub-core/gnulib/stdlib.h +grub-core/gnulib/string.h +grub-core/gnulib/strings.h +grub-core/gnulib/sys +grub-core/gnulib/unistd.h +grub-core/gnulib/warn-on-use.h +grub-core/gnulib/wchar.h +grub-core/gnulib/wctype.h +grub-core/rs_decoder.h +widthspec.bin +widthspec.h +docs/stamp-1 +docs/version-dev.texi +Makefile.utilgcry.def +po/*.po +po/*.gmo +po/LINGUAS +po/remove-potcdate.sed +include/grub/gcrypt/gcrypt.h +include/grub/gcrypt/g10lib.h +po/POTFILES.in +po/POTFILES-shell.in +/grub-glue-efi +/grub-render-label +/grub-glue-efi.exe +/grub-render-label.exe +grub-core/gnulib/locale.h +grub-core/gnulib/unitypes.h +grub-core/gnulib/uniwidth.h +build-aux/test-driver +/garbage-gen +/garbage-gen.exe +/grub-fs-tester +!util/grub.d/[[:digit:]][[:digit:]]*.in +!util/*.[[:digit:]] diff --git a/SOURCES/grub.macros b/SOURCES/grub.macros new file mode 100644 index 0000000..20a2f97 --- /dev/null +++ b/SOURCES/grub.macros @@ -0,0 +1,510 @@ +# vim:filetype=spec + +%global flagday 1:2.02-0.65.el7_4 + +# Modules always contain just 32-bit code +%global _libdir %{_exec_prefix}/lib +%global _binaries_in_noarch_packages_terminate_build 0 +#%%undefine _missing_build_ids_terminate_build +%{expand:%%{!?buildsubdir:%%global buildsubdir grub-%{tarversion}}} +%{expand:%%{!?_licensedir:%%global license %%%%doc}} + +%if %{?_with_ccache: 1}%{?!_with_ccache: 0} +%global cc_equals CC=/usr/%{_lib}/ccache/gcc +%else +%global cc_equals %{nil} +%endif + +%global efi_cflags %(echo %{optflags} | \\\ + sed \\\ + -e 's/-O./-g3/g' \\\ + -e 's/-fstack-protector[[:alpha:]-]\\+//g' \\\ + -e 's/-Wp,-D_FORTIFY_SOURCE=[[:digit:]]\\+//g' \\\ + -e 's/--param=ssp-buffer-size=4//g' \\\ + -e 's/-mregparm=3/-mregparm=4/g' \\\ + -e 's/-fexceptions//g' \\\ + -e 's/-fasynchronous-unwind-tables//g' \\\ + -e 's/^/ -fno-strict-aliasing /' ) %{nil} +%global legacy_cflags %(echo %{efi_cflags} | \\\ + sed \\\ + -e 's/-m64//g' \\\ + -e 's/-mcpu=power[[:alnum:]]\\+/-mcpu=power6/g' \\\ + ) %{nil} + + +%global with_efi_arch 0 +%global with_alt_efi_arch 0 +%global with_legacy_arch 0 +%global with_legacy_utils 0 +%global grubefiarch %{nil} +%global grublegacyarch %{nil} + +# sparc is always compiled 64 bit +%ifarch %{sparc} +%global target_cpu_name sparc64 +%global _target_platform %{target_cpu_name}-%{_vendor}-%{_target_os}%{?_gnu} +%global legacy_target_cpu_name %{_arch} +%global legacy_package_arch ieee1275 +%global platform ieee1275 +%endif +# ppc is always compiled 64 bit +%ifarch ppc ppc64 ppc64le +%global target_cpu_name %{_arch} +%global legacy_target_cpu_name powerpc +%global legacy_package_arch %{_arch} +%global legacy_grub_dir powerpc-ieee1275 +%global _target_platform %{target_cpu_name}-%{_vendor}-%{_target_os}%{?_gnu} +%global platform ieee1275 +%endif + +%global efi_only aarch64 %{arm} +%global efi_arch x86_64 ia64 %{efi_only} +%ifarch %{efi_arch} +%global with_efi_arch 1 +%else +%global with_efi_arch 0 +%endif +%ifarch %{efi_only} +%global with_efi_only 1 +%else +%global with_efi_only 0 +%endif +%{!?with_efi_arch:%global without_efi_arch 0} +%{?with_efi_arch:%global without_efi_arch 1} +%{!?with_efi_only:%global without_efi_only 0} +%{?with_efi_only:%global without_efi_only 1} + +### fixme +%ifarch aarch64 %{arm} +%global efi_modules " http linux " +%else +%global efi_modules " backtrace http linuxefi usb usbserial_common usbserial_pl2303 usbserial_ftdi usbserial_usbdebug " +%endif + +%ifarch x86_64 +%global efiarch x64 +%global target_cpu_name %{_arch} +%global grub_target_name %{_arch}-efi +%global package_arch efi-x64 + +%global legacy_target_cpu_name i386 +%global legacy_package_arch pc +%global platform pc + +%global alt_efi_arch ia32 +%global alt_target_cpu_name i386 +%global alt_grub_target_name i386-efi +%global alt_platform efi +%global alt_package_arch efi-ia32 +%global alt_efi_cflags %(echo %{efi_cflags} | \\\ + sed \\\ + -e 's/-m64//g' \\\ + ) %{nil} +%endif +%ifarch %{ix86} +%global target_cpu_name %{_arch} +%global grub_target_name %{_arch}-pc + +%global legacy_target_cpu_name i386 +%global legacy_package_arch pc +%global platform pc + +%global with_legacy_arch 0 +%endif + +%ifarch aarch64 +%global efiarch aa64 +%global target_cpu_name aarch64 +%global grub_target_name arm64-efi +%global package_arch efi-aa64 +%endif + +%ifarch %{arm} +%global efiarch arm +%global target_cpu_name arm +%global grub_target_name arm-efi +%global package_arch efi-arm +%endif + +%global _target_platform %{target_cpu_name}-%{_vendor}-%{_target_os}%{?_gnu} +%global _alt_target_platform %{alt_target_cpu_name}-%{_vendor}-%{_target_os}%{?_gnu} + +%ifarch %{efi_arch} +%global with_efi_arch 1 +%global grubefiname grub%{efiarch}.efi +%global grubeficdname gcd%{efiarch}.efi +%global grubefiarch %{target_cpu_name}-efi +%endif + +%if 0%{?alt_efi_arch:1} +%global with_alt_efi_arch 1 +%global grubaltefiname grub%{alt_efi_arch}.efi +%global grubalteficdname gcd%{alt_efi_arch}.efi +%global grubaltefiarch %{alt_target_cpu_name}-efi +%endif + +# Figure out the right file path to use +%global efidir %(eval echo $(grep ^ID= /etc/os-release | sed -e 's/^ID=//' -e 's/rhel/redhat/')) + +%ifnarch %{efi_only} +%global with_legacy_arch 1 +%global with_legacy_utils 1 +%global grublegacyarch %{legacy_target_cpu_name}-%{platform} +%global moduledir %{legacy_target_cpu_name}-%{platform} +%endif + +%global evr %{epoch}:%{version}-%{release} + +%if %{with_legacy_arch} +%global with_efi_common 0 +%global with_legacy_common 1 +%else +%global with_efi_common 1 +%global with_legacy_common 0 +%endif +%ifarch %{ix86} +%global with_efi_arch 0 +%global with_alt_efi_arch 0 +%global with_efi_common 0 +%global with_legacy_common 1 +%global with_legacy_utils 1 +%global with_legacy_arch 0 +%endif + +%if 0%{with_efi_common} +%global common_srcdir grub-%{grubefiarch}-%{tarversion} +%endif +%if 0%{with_legacy_common} +%global common_srcdir grub-%{grublegacyarch}-%{tarversion} +%endif + +%define define_legacy_variant() \ +%{expand:%%package %{1}} \ +Summary: Bootloader with support for Linux, Multiboot, and more \ +Group: System Environment/Base \ +Requires: %{name}-common = %{evr} \ +Requires: %{name}-tools-minimal = %{evr} \ +Requires: %{name}-%{1}-modules = %{evr} \ +Requires: gettext which file \ +Requires: %{name}-tools-extra = %{evr} \ +Requires: %{name}-tools = %{evr} \ +Requires(pre): dracut \ +Requires(post): dracut \ +%{expand:%%description %{1}} \ +%{desc} \ +This subpackage provides support for %{1} systems. \ + \ +%{expand:%%{?!buildsubdir:%%define buildsubdir grub-%{1}-%{tarversion}}}\ +%{expand:%%package %{1}-modules} \ +Summary: Modules used to build custom grub images \ +Group: System Environment/Base \ +BuildArch: noarch \ +Requires: %{name}-common = %{evr} \ +%{expand:%%description %{1}-modules} \ +%{desc} \ +This subpackage provides support for rebuilding your own grub.efi. \ + \ +%{expand:%%{?!buildsubdir:%%define buildsubdir grub-%{1}-%{tarversion}}}\ +%{expand:%%package %{1}-tools} \ +Summary: Support tools for GRUB. \ +Group: System Environment/Base \ +Requires: gettext os-prober which file system-logos \ +Requires: %{name}-common = %{evr} \ +Requires: %{name}-tools-minimal = %{evr} \ +Requires: os-prober >= 1.58-11 \ +Requires: gettext which file \ + \ +%{expand:%%description %{1}-tools} \ +%{desc} \ +This subpackage provides tools for support of %{1} platforms. \ +%{nil} + +%define define_efi_variant(p) \ +%{expand:%%package %{1}} \ +Summary: GRUB for EFI systems. \ +Group: System Environment/Base \ +Requires: %{name}-common = %{evr} \ +Requires: %{name}-tools-minimal >= %{evr} \ +Requires: %{name}-tools-extra = %{evr} \ +Requires: %{name}-tools = %{evr} \ +%{-p:Provides: %{name}-efi = %{evr}} \ +%{-p:Obsoletes: %{name}-efi <= %{flagday}} \ + \ +%{expand:%%description %{1}} \ +%{desc} \ +This subpackage provides support for %{1} systems. \ + \ +%{expand:%%{?!buildsubdir:%%define buildsubdir grub-%{1}-%{tarversion}}}\ +%{expand:%%package %{1}-modules} \ +Summary: Modules used to build custom grub.efi images \ +Group: System Environment/Base \ +BuildArch: noarch \ +Requires: %{name}-common = %{evr} \ +%{-p:Provides: %{name}-efi-modules = %{evr}} \ +%{-p:Obsoletes: %{name}-efi-modules <= %{flagday}} \ +%{expand:%%description %{1}-modules} \ +%{desc} \ +This subpackage provides support for rebuilding your own grub.efi. \ + \ +%{expand:%%package %{1}-cdboot} \ +Summary: Files used to boot removeable media with EFI \ +Group: System Environment/Base \ +Requires: %{name}-common = %{evr} \ +%{expand:%%description %{1}-cdboot} \ +%{desc} \ +This subpackage provides optional components of grub used with removeable media on %{1} systems.\ +%{nil} + +%global do_common_setup() \ +%setup -D -q -T -a 0 -n grub-%{tarversion} \ +cd grub-%{tarversion} \ +rm -fv docs/*.info \ +cp %{SOURCE5} unifont.pcf.gz \ +cp %{SOURCE6} .gitignore \ +git init \ +echo '![[:digit:]][[:digit:]]_*.in' > util/grub.d/.gitignore \ +echo '!*.[[:digit:]]' > util/.gitignore \ +git config user.email "%{name}-owner@fedoraproject.org" \ +git config user.name "Fedora Ninjas" \ +git config gc.auto 0 \ +git add . \ +git commit -a -q -m "%{tarversion} baseline." \ +git am %%{patches} = 0.99-8 +%endif +%if %{?_with_ccache: 1}%{?!_with_ccache: 0} +BuildRequires: ccache +%endif + +ExcludeArch: s390 s390x %{arm} %{?ix86} +Obsoletes: %{name} <= %{flagday} + +%if 0%{with_legacy_arch} +Requires: %{name}-%{legacy_package_arch} = %{evr} +%else +Requires: %{name}-%{package_arch} = %{evr} +%endif + +%global desc \ +The GRand Unified Bootloader (GRUB) is a highly configurable and \ +customizable bootloader with modular architecture. It supports a rich \ +variety of kernel formats, file systems, computer architectures and \ +hardware devices.\ +%{nil} + +%description +%{desc} + +%ifarch x86_64 +%package common +Summary: grub2 common layout +Group: System Environment/Base +BuildArch: noarch + +%description common +This package provides some directories which are required by various grub2 +subpackages. +%endif + +%package tools +Summary: Support tools for GRUB. +Group: System Environment/Base +Obsoletes: %{name}-tools <= %{flagday} +%ifarch x86_64 +Obsoletes: %{name}-tools-efi <= %{flagday} +Provides: %{name}-tools-efi = %{evr} +%endif +Requires: %{name}-tools-minimal = %{evr} +Requires: %{name}-common = %{evr} +Requires: gettext os-prober which file +Requires(pre): dracut +Requires(post): dracut + +%description tools +%{desc} +This subpackage provides tools for support of all platforms. + +%package tools-minimal +Summary: Support tools for GRUB. +Group: System Environment/Base +Requires: gettext +Requires: %{name}-common = %{evr} +Obsoletes: %{name}-tools <= %{flagday} + +%description tools-minimal +%{desc} +This subpackage provides tools for support of all platforms. + +%package tools-extra +Summary: Support tools for GRUB. +Group: System Environment/Base +Requires: gettext os-prober which file +Requires: %{name}-tools-minimal = %{epoch}:%{version}-%{release} +Requires: %{name}-common = %{epoch}:%{version}-%{release} +Requires: %{name}-tools = %{evr} +Obsoletes: %{name}-tools <= %{flagday} + +%description tools-extra +%{desc} +This subpackage provides tools for support of all platforms. + +%if 0%{with_efi_arch} +%define_efi_variant %{package_arch} -p +%endif +%if 0%{with_alt_efi_arch} +%define_efi_variant %{alt_package_arch} +%endif +%if 0%{with_legacy_arch} +%define_legacy_variant %{legacy_package_arch} +%endif + +%prep +%setup -T -c -n grub-%{tarversion} +%do_common_setup +%if 0%{with_efi_arch} +%do_setup %{grubefiarch} +%endif +%if 0%{with_alt_efi_arch} +%do_setup %{grubaltefiarch} +%endif +%if 0%{with_legacy_arch}%{with_legacy_utils} +%do_setup %{grublegacyarch} +%endif + +%build +%if 0%{with_efi_arch} +%do_primary_efi_build %{grubefiarch} %{grubefiname} %{grubeficdname} %{_target_platform} "'%{efi_cflags}'" %{SOURCE3} %{SOURCE4} redhatsecureboot301 +%endif +%if 0%{with_alt_efi_arch} +%do_alt_efi_build %{grubaltefiarch} %{grubaltefiname} %{grubalteficdname} %{_alt_target_platform} "'%{alt_efi_cflags}'" %{SOURCE3} %{SOURCE4} redhatsecureboot301 +%endif +%if 0%{with_legacy_arch}%{with_legacy_utils} +%do_legacy_build %{grublegacyarch} +%endif +%do_common_build + +%install +set -e +rm -fr $RPM_BUILD_ROOT + +%do_common_install +%if 0%{with_efi_arch} +%do_efi_install %{grubefiarch} %{grubefiname} %{grubeficdname} +%endif +%if 0%{with_alt_efi_arch} +%do_alt_efi_install %{grubaltefiarch} %{grubaltefiname} %{grubalteficdname} +%endif +%if 0%{with_legacy_arch}%{with_legacy_utils} +%do_legacy_install %{grublegacyarch} %{alt_grub_target_name} +%endif +${RPM_BUILD_ROOT}/%{_bindir}/%{name}-editenv ${RPM_BUILD_ROOT}/boot/efi/EFI/%{efidir}/grubenv create +rm -f $RPM_BUILD_ROOT%{_infodir}/dir + +%find_lang grub + +# Make selinux happy with exec stack binaries. +mkdir ${RPM_BUILD_ROOT}%{_sysconfdir}/prelink.conf.d/ +cat << EOF > ${RPM_BUILD_ROOT}%{_sysconfdir}/prelink.conf.d/grub2.conf +# these have execstack, and break under selinux +-b /usr/bin/grub2-script-check +-b /usr/bin/grub2-mkrelpath +-b /usr/bin/grub2-fstest +-b /usr/sbin/grub2-bios-setup +-b /usr/sbin/grub2-probe +-b /usr/sbin/grub2-sparc64-setup +EOF + +# Don't run debuginfo on all the grub modules and whatnot; it just +# rejects them, complains, and slows down extraction. +%global finddebugroot "%{_builddir}/%{?buildsubdir}/debug" + +%global dip RPM_BUILD_ROOT=%{finddebugroot} %{__debug_install_post} +%define __debug_install_post ( \ + mkdir -p %{finddebugroot}/usr \ + mv ${RPM_BUILD_ROOT}/usr/bin %{finddebugroot}/usr/bin \ + mv ${RPM_BUILD_ROOT}/usr/sbin %{finddebugroot}/usr/sbin \ + %{dip} \ + install -m 0755 -d %{buildroot}/usr/lib/ %{buildroot}/usr/src/ \ + cp -al %{finddebugroot}/usr/lib/debug/ \\\ + %{buildroot}/usr/lib/debug/ \ + cp -al %{finddebugroot}/usr/src/debug/ \\\ + %{buildroot}/usr/src/debug/ ) \ + mv %{finddebugroot}/usr/bin %{buildroot}/usr/bin \ + mv %{finddebugroot}/usr/sbin %{buildroot}/usr/sbin \ + %{nil} + +%clean +rm -rf $RPM_BUILD_ROOT + +%pre tools +if [ -f /boot/grub2/user.cfg ]; then + if grep -q '^GRUB_PASSWORD=' /boot/grub2/user.cfg ; then + sed -i 's/^GRUB_PASSWORD=/GRUB2_PASSWORD=/' /boot/grub2/user.cfg + fi +elif [ -f /boot/efi/EFI/%{efidir}/user.cfg ]; then + if grep -q '^GRUB_PASSWORD=' /boot/efi/EFI/%{efidir}/user.cfg ; then + sed -i 's/^GRUB_PASSWORD=/GRUB2_PASSWORD=/' \ + /boot/efi/EFI/%{efidir}/user.cfg + fi +elif [ -f /etc/grub.d/01_users ] && \ + grep -q '^password_pbkdf2 root' /etc/grub.d/01_users ; then + if [ -f /boot/efi/EFI/%{efidir}/grub.cfg ]; then + # on EFI we don't get permissions on the file, but + # the directory is protected. + grep '^password_pbkdf2 root' /etc/grub.d/01_users | \ + sed 's/^password_pbkdf2 root \(.*\)$/GRUB2_PASSWORD=\1/' \ + > /boot/efi/EFI/%{efidir}/user.cfg + fi + if [ -f /boot/grub2/grub.cfg ]; then + install -m 0600 /dev/null /boot/grub2/user.cfg + chmod 0600 /boot/grub2/user.cfg + grep '^password_pbkdf2 root' /etc/grub.d/01_users | \ + sed 's/^password_pbkdf2 root \(.*\)$/GRUB2_PASSWORD=\1/' \ + > /boot/grub2/user.cfg + fi +fi +if [ -f /boot/grub2/grubenv ] && ! [ -f /boot/efi/EFI/%{efidir}/grubenv ] ; then + if [ -e /boot/efi/EFI/%{efidir}/grubenv ] ; then + rm /boot/efi/EFI/%{efidir}/grubenv + mv /boot/grub2/grubenv /boot/efi/EFI/%{efidir}/grubenv + ln -sf ../efi/EFI/%{efidir}/grubenv /boot/grub2/grubenv + fi +fi + +%post tools +if [ "$1" = 1 ]; then + /sbin/install-info --info-dir=%{_infodir} %{_infodir}/%{name}.info.gz || : + /sbin/install-info --info-dir=%{_infodir} %{_infodir}/%{name}-dev.info.gz || : +fi + +%triggerun -- grub2 < 1:1.99-4 +# grub2 < 1.99-4 removed a number of essential files in postun. To fix upgrades +# from the affected grub2 packages, we first back up the files in triggerun and +# later restore them in triggerpostun. +# https://bugzilla.redhat.com/show_bug.cgi?id=735259 + +# Back up the files before uninstalling old grub2 +mkdir -p /boot/grub2.tmp && +mv -f /boot/grub2/*.mod \ + /boot/grub2/*.img \ + /boot/grub2/*.lst \ + /boot/grub2/device.map \ + /boot/grub2.tmp/ || : + +%triggerpostun -- grub2 < 1:1.99-4 +# ... and restore the files. +test ! -f /boot/grub2/device.map && +test -d /boot/grub2.tmp && +mv -f /boot/grub2.tmp/*.mod \ + /boot/grub2.tmp/*.img \ + /boot/grub2.tmp/*.lst \ + /boot/grub2.tmp/device.map \ + /boot/grub2/ && +rm -r /boot/grub2.tmp/ || : + +%preun tools +if [ "$1" = 0 ]; then + /sbin/install-info --delete --info-dir=%{_infodir} %{_infodir}/%{name}.info.gz || : + /sbin/install-info --delete --info-dir=%{_infodir} %{_infodir}/%{name}-dev.info.gz || : +fi + +%files +%ifnarch x86_64 %{ix86} +%exclude %{_bindir}/%{name}-render-label +%exclude %{_sbindir}/%{name}-bios-setup +%exclude %{_sbindir}/%{name}-macbless +%endif +%ifnarch x86_64 +%exclude /boot/grub2/grubenv +%exclude /boot/efi/EFI/*/grubenv +%exclude %{_datadir}/locale +%endif + +%ifarch x86_64 +%files common -f grub.lang +%dir %{_libdir}/grub/ +%dir %{_datarootdir}/grub/ +%dir %{_datarootdir}/grub/themes/ +%exclude %{_datarootdir}/grub/themes/* +%attr(0700,root,root) %dir %{_sysconfdir}/grub.d +%dir %{_datarootdir}/grub +%exclude %{_datarootdir}/grub/* +%dir /boot/%{name} +%dir /boot/%{name}/themes/ +%dir /boot/%{name}/themes/system +%exclude /boot/%{name}/themes/system/* +%attr(0700,root,root) %dir /boot/grub2 +%exclude /boot/grub2/* +%dir %verify(not mtime) %attr(0700,root,root)/boot/efi/EFI/%{efidir} +%exclude /boot/efi/EFI/%{efidir}/* +%license %{common_srcdir}/COPYING +%ghost %config(noreplace) /boot/grub2/grubenv +%doc %{common_srcdir}/INSTALL +%doc %{common_srcdir}/NEWS +%doc %{common_srcdir}/README +%doc %{common_srcdir}/THANKS +%doc %{common_srcdir}/TODO +%doc %{common_srcdir}/docs/grub.html +%doc %{common_srcdir}/docs/grub-dev.html +%doc %{common_srcdir}/docs/font_char_metrics.png +%endif + +%files tools-minimal +%defattr(-,root,root,-) +%{_sysconfdir}/prelink.conf.d/grub2.conf +%{_sbindir}/%{name}-get-kernel-settings +%{_sbindir}/%{name}-set-default +%{_sbindir}/%{name}-setpassword +%{_bindir}/%{name}-editenv +%{_bindir}/%{name}-mkpasswd-pbkdf2 + +%{_datadir}/man/man3/%{name}-get-kernel-settings* +%{_datadir}/man/man8/%{name}-set-default* +%{_datadir}/man/man8/%{name}-setpassword* +%{_datadir}/man/man1/%{name}-editenv* +%{_datadir}/man/man1/%{name}-mkpasswd-* + +%files tools +%defattr(-,root,root,-) +%attr(0644,root,root) %ghost %config(noreplace) %{_sysconfdir}/default/grub +%config %{_sysconfdir}/grub.d/??_* +%{_sysconfdir}/grub.d/README +%{_infodir}/%{name}* +%{_datarootdir}/grub/* +%exclude %{_datarootdir}/grub/themes +%exclude %{_datarootdir}/grub/*.h +%{_datarootdir}/bash-completion/completions/grub +%{_sbindir}/%{name}-install +%{_sbindir}/%{name}-mkconfig +%{_sbindir}/%{name}-probe +%{_sbindir}/%{name}-rpm-sort +%{_sbindir}/%{name}-reboot +%{_bindir}/%{name}-file +%{_bindir}/%{name}-menulst2cfg +%{_bindir}/%{name}-mkrelpath +%{_bindir}/%{name}-script-check +%{_datadir}/man/man?/* + +# exclude man pages from tools-extra +%exclude %{_datadir}/man/man8/%{name}-sparc64-setup* +%exclude %{_datadir}/man/man8/%{name}-install* +%exclude %{_datadir}/man/man1/%{name}-fstest* +%exclude %{_datadir}/man/man1/%{name}-glue-efi* +%exclude %{_datadir}/man/man1/%{name}-kbdcomp* +%exclude %{_datadir}/man/man1/%{name}-mkfont* +%exclude %{_datadir}/man/man1/%{name}-mkimage* +%exclude %{_datadir}/man/man1/%{name}-mklayout* +%exclude %{_datadir}/man/man1/%{name}-mknetdir* +%exclude %{_datadir}/man/man1/%{name}-mkrescue* +%exclude %{_datadir}/man/man1/%{name}-mkstandalone* +%exclude %{_datadir}/man/man1/%{name}-syslinux2cfg* + +# exclude man pages from tools-minimal +%exclude %{_datadir}/man/man3/%{name}-get-kernel-settings* +%exclude %{_datadir}/man/man8/%{name}-set-default* +%exclude %{_datadir}/man/man8/%{name}-setpassword* +%exclude %{_datadir}/man/man1/%{name}-editenv* +%exclude %{_datadir}/man/man1/%{name}-mkpasswd-* + +%ifarch x86_64 %{?ix86} +%{_sbindir}/%{name}-macbless +%{_bindir}/%{name}-render-label +%{_datadir}/man/man8/%{name}-macbless* +%{_datadir}/man/man1/%{name}-render-label* +%else +%exclude %{_sbindir}/%{name}-macbless +%exclude %{_bindir}/%{name}-render-label +%exclude %{_datadir}/man/man8/%{name}-macbless* +%exclude %{_datadir}/man/man1/%{name}-render-label* +%endif + +%if %{with_legacy_utils} +%{_sbindir}/%{name}-install +%ifarch %{ix86} x86_64 +%{_sbindir}/%{name}-bios-setup +%else +%exclude %{_sbindir}/%{name}-bios-setup +%exclude %{_datadir}/man/man8/%{name}-bios-setup* +%endif +%ifarch %{sparc} +%{_sbindir}/%{name}-sparc64-setup +%else +%exclude %{_sbindir}/%{name}-sparc64-setup +%exclude %{_datadir}/man/man8/%{name}-sparc64-setup* +%endif +%ifarch %{sparc} ppc ppc64 ppc64le +%{_sbindir}/%{name}-ofpathname +%else +%exclude %{_sbindir}/%{name}-ofpathname +%exclude %{_datadir}/man/man8/%{name}-ofpathname* +%endif +%endif + +%files tools-extra +%{_sbindir}/%{name}-sparc64-setup +%{_sbindir}/%{name}-ofpathname +%{_bindir}/%{name}-fstest +%{_bindir}/%{name}-glue-efi +%{_bindir}/%{name}-kbdcomp +%{_bindir}/%{name}-mkfont +%{_bindir}/%{name}-mkimage +%{_bindir}/%{name}-mklayout +%{_bindir}/%{name}-mknetdir +%ifnarch %{sparc} +%{_bindir}/%{name}-mkrescue +%endif +%{_bindir}/%{name}-mkstandalone +%{_bindir}/%{name}-syslinux2cfg +%{_sysconfdir}/sysconfig/grub +%{_datadir}/man/man8/%{name}-sparc64-setup* +%{_datadir}/man/man8/%{name}-install* +%{_datadir}/man/man1/%{name}-fstest* +%{_datadir}/man/man1/%{name}-glue-efi* +%{_datadir}/man/man1/%{name}-kbdcomp* +%{_datadir}/man/man1/%{name}-mkfont* +%{_datadir}/man/man1/%{name}-mkimage* +%{_datadir}/man/man1/%{name}-mklayout* +%{_datadir}/man/man1/%{name}-mknetdir* +%{_datadir}/man/man1/%{name}-mkrescue* +%{_datadir}/man/man1/%{name}-mkstandalone* +%{_datadir}/man/man8/%{name}-ofpathname* +%{_datadir}/man/man1/%{name}-syslinux2cfg* +%exclude %{_datarootdir}/grub/themes/starfield + +%if 0%{with_efi_arch} +%define_efi_variant_files %{package_arch} %{grubefiname} %{grubeficdname} %{grubefiarch} %{target_cpu_name} %{grub_target_name} +%endif +%if 0%{with_alt_efi_arch} +%define_efi_variant_files %{alt_package_arch} %{grubaltefiname} %{grubalteficdname} %{grubaltefiarch} %{alt_target_cpu_name} %{alt_grub_target_name} +%endif +%if 0%{with_legacy_arch} +%define_legacy_variant_files %{legacy_package_arch} %{grublegacyarch} +%else +%if 0%{with_legacy_utils} +%exclude %{_sysconfdir}/%{name}.cfg +%exclude %{_libdir}/grub/%{grublegacyarch}/* +%exclude %{_libdir}/grub/%{grublegacyarch}/ +%endif +%endif + +%changelog +* Fri Sep 13 2019 Javier Martinez Canillas - 2.02-0.81 +- Only make grub2-tools Obsoletes and Provides grub2-tools-efi for x86_64 + Resolves: rhbz#1748019 + +* Wed Mar 27 2019 Javier Martinez Canillas - 2.02-0.80 +- Rebuild with correct build target for signing + Resolves: rhbz#1693213 + +* Tue Mar 26 2019 Javier Martinez Canillas - 2.02-0.79 +- Ignore the modification time when doing RPM verification of /boot/efi files + Resolves: rhbz#1496952 + +* Wed Mar 20 2019 Javier Martinez Canillas - 2.02-0.78 +- Prevent errors from diskfilter scan of removable drives + Resolves: rhbz#1446418 +- Avoid grub2-efi package to overwrite existing /boot/grub2/grubenv file + Resolves: rhbz#1497918 +- Remove glibc32 and glibc-static(x86-32) BuildRequires + Resolves: rhbz#1614259 + +* Thu Oct 25 2018 Javier Martinez Canillas - 2.02-0.77 +- Re-enable regexp module + Resolves: rhbz#1630678 + +* Mon Jul 30 2018 pjones - 2.02.0.76 +- Fix PCIe probing in EFI UGA driver. + Resolves: rhbz#1583708 + +* Wed Jul 18 2018 Peter Jones - 2.02-0.74 +- Fix symlink issues with grubenv + Resolves: rhbz#1602773 + Related: rhbz#1497918 +- Make the common subpackage only build on x86_64 to avoid timestamp + mismatches. + Related: rhbz#1602773 + Related: rhbz#1497918 + +* Fri Jun 29 2018 Peter Jones - 2.02-0.73 +- Fix loading grub modules with no symbols defined. + Related: rhbz#1490981 + +* Thu Jun 28 2018 Peter Jones - 2.02-0.72 +- Revert module dir fix; it still doesn't work. + Resolves: rhbz#1594703 + +* Mon Jun 25 2018 Peter Jones - 2.02-0.71 +- The change from 2.02-0.65.el7_4.2 never made it onto the main branch, + so one more build to avoid the regression. + Related: rhbz#1340893 + +* Mon Jun 25 2018 Peter Jones 2.02-0.70 +- ... and once more, because I built for the wrong target. + Related: rhbz#1340893 + +* Mon Jun 25 2018 Peter Jones - 2.02-0.69 +- Build utilities on i686 as well, so grubby can build-dep it there. + Related: rhbz#1340893 + +* Fri Jun 22 2018 Peter Jones - 2.02-0.68 +- More work on /boot/efi/... permissions + Resolves: rhbz#1496952 +- Rework grubenv symlinks and handle them on upgrades + Resolves: rhbz#1497918 +- Make grub2-setpassword -o work + Resolves: rhbz#1512749 + +* Thu Jun 21 2018 Peter Jones - 2.02-0.67 +- Make the permissions on /boot/efi/... match the filesystem's requirements. + Resolves: rhbz#1496952 + +* Thu Jun 21 2018 Peter Jones - 2.02-0.66 +- Fix EFI UGA driver when the framebuffer is above 4G + Resolves: rhbz#1457988 +- Handle XFS filesystems with sparse inodes + Resolves: rhbz#1402716 +- Support HTTP booting + Resolves: rhbz#1490981 + +* Mon Oct 09 2017 Peter Jones - 2.02-0.65.el7_4.2 +- Fix an incorrect man page exclusion on x86_64. + +* Fri Oct 06 2017 Peter Jones - 2.02-0.65.1 +- More precise requires and obsoletes on the -tools* subpackages to avoid + issues with mixing and matching repos the subpackages are split between. + +* Fri Sep 22 2017 Peter Jones - 2.02-0.65 +- Fix spurious : at the end of the mac address netboot paths. + Resolves: rhbz#1483740 + +* Wed May 31 2017 Peter Jones - 2.02-0.64 +- Revert pkglibdir usage; we have to coordinate this with Lorax. + Related: rhbz#1455243 + +* Tue May 30 2017 pjones - 2.02-0.63 +- Fix grub2-mkimage on ppc* to *also* deal with pkglibdir changing. + Related: rhbz#1455243 + +* Tue May 30 2017 Peter Jones - 2.02-0.62 +- Fix grub2-mkimage on ppc* to *also* deal with pkglibdir changing. + Related: rhbz#1455243 + +* Wed May 24 2017 Peter Jones - 2.02-0.61 +- Fix some minor ia32 booting bugs + Related: rhbz#1310763 + Related: rhbz#1411748 + Related: rhbz#1300009 +- Add support for non-Ethernet network cards + Related: rhbz#1232432 +- Add support for http booting + Resolves: rhbz#1232432 +- Fix efi module subpackage obsoletes/provides + Resolves: rhbz#1447723 +- Make ppc modules subpackages use different directories on the filesystem. + Resolves: rhbz#1455243 + +* Thu Apr 20 2017 Peter Jones - 2.02-0.60 +- Fix ppc64 deciding /boot/efi might somehow be the CHRP partition if it + exists. This is also why the bug we fixed in 0.59 showed up at all. + Resolves: rhbz#1443809 + Resolves: rhbz#1442970 +- Fix a regexp problem where rpm spec parser un-escapes things that + don't need escaping, which causes our s/-mcpu=power8/-mcpu=power6/ + to fail. + Related: rhbz#1443809 + +* Wed Apr 19 2017 Peter Jones - 2.02-0.59 +- Fix ppc64 "grub2.chrp" to be "grub.chrp" harder + Resolves: rhbz#1442970 + +* Wed Apr 19 2017 Peter Jones - 2.02-0.58 +- Add Aarch64 FDT #address-cells and #size-cells support + Resolves: rhbz#1436745 +- Fix ppc64 "grub2.chrp" to be "grub.chrp" + Resolves: rhbz#1442970 + +* Wed Apr 12 2017 Peter Jones - 2.02-0.57 +- Make "grub2" require the grub2-efi-... package on arches where there's no + legacy build. + Related: rhbz#1440787 + +* Tue Apr 11 2017 Peter Jones - 2.02-0.56 +- Rebuild in the right build root. + Related: rhbz#1437450 + +* Tue Apr 11 2017 Peter Jones - 2.02-0.55 +- Make a "grub2" top-level package to help solve Jira RCM-14929. + Related: rhbz#1437450 + +* Mon Apr 10 2017 Peter Jones - 2.02-0.54 +- Make grub2-pc, grub2-ppc64le, etc, also have an Obsoletes for the old grub2 + packages. Hoping this will solve Jira RCM-14929. + Related: rhbz#1437450 + +* Thu Mar 30 2017 Peter Jones - 2.02-0.53 +- Don't manually put an arch in a requires. + The automatically generated provides won't have it, and all of the + tools display the packages as if it were there, so you can't ever see + that they never match up. Meanwhile the auto generator *will* add + $name($arch)=$evr provides, which aren't quite the same. We probably + don't need it anyway. Maybe. + Resolves: rhbz#1437450 + +* Thu Mar 30 2017 Peter Jones - 2.02-0.52 +- Fix our debuginfo filter to not accidentally discard the stripped versions of + userland binaries. + Related: rhbz#1310763 + +* Tue Mar 28 2017 Peter Jones - 2.02-0.51 +- Also be sure to pull in grub2-tools-extras for now, to make upgrades work. + Related: rhbz#1310763 + +* Tue Mar 28 2017 Peter Jones - 2.02-0.50 +- Fix where the grub2-ofpathname man page lands + Related: rhbz#1310763 +- Fix stripping of userland binaries + Related: rhbz#1310763 + +* Tue Mar 21 2017 Peter Jones - 2.02-0.49 +- Include unicode.pf2 in the grub-efi-ARCH-cdboot images + Related: rhbz#1310763 + Related: rhbz#1411748 + Related: rhbz#1300009 + +* Tue Mar 21 2017 Peter Jones - 2.02-0.48 +- grub2-efi-* don't actually need to require grub2-tools-efi (i.e. the mac + tools), anaconda and lorax can know how to do that. + Related: rhbz#1310763 + Related: rhbz#1411748 + Related: rhbz#1300009 + +* Mon Mar 20 2017 Peter Jones - 2.02-0.47 +- Fix ia32 booting. + Related: rhbz#1310763 + Related: rhbz#1411748 + Related: rhbz#1300009 + +* Fri Mar 17 2017 Peter Jones - 2.02-0.46 +- Fix ppc* package names. + Related: rhbz#1310763 + Related: rhbz#1411748 + Related: rhbz#1300009 + +* Wed Mar 15 2017 Peter Jones - 2.02-0.45 +- Rework package to make multi-arch EFI easier. + Resolves: rhbz#1310763 + Related: rhbz#1411748 +- Honor IO alignment on EFI systems + Resolves: rhbz#1300009 + +* Mon Aug 29 2016 Peter Jones - 2.02-0.44 +- Work around tftp servers that don't work with multiple consecutive slashes in + file paths. + Resolves: rhbz#1217243 + +* Thu Aug 25 2016 Peter Jones - 2.02-0.42 +- Make grub2-mkconfig export grub2-get-kernel-settings variables correctly. + Related: rhbz#1226325 + +* Tue Aug 23 2016 Peter Jones - 2.02-0.42 +- Rebuild in the right build root. Again. + Related: rhbz#1273974 + +* Wed Jul 13 2016 Peter Jones - 2.02-0.41 +- Build with coverity patch I missed last time. + Related: rhbz#1226325 + +* Wed Jul 13 2016 rmarshall@redhat.com - 2.02-0.40 +- Build with coverity patches. + Related: rhbz#1226325 + +* Wed Jul 13 2016 Peter Jones +- Remove our patch to force a paricular uefi network interface + Related: rhbz#1273974 + Related: rhbz#1277599 + Related: rhbz#1298765 +- Update some more coverity issues + Related: rhbz#1226325 + Related: rhbz#1154226 + +* Mon Jul 11 2016 rmarshall@redhat.com - 2.02-0.39 +- Fix all issues discovered during coverity scan. + Related: rhbz#1154226 +- Fix a couple compiler and CLANG issues discovered during coverity scan. + Related: rhbz#1154226 +- Fix the last few CLANG issues and a deadcode issue discovered by the + coverity scan. + Related: rhbz#1154226 + +* Fri Jul 01 2016 Peter Jones - 2.02-0.38 +- Pick the right build target. Again. + Related: rhbz#1226325 + +* Tue Jun 21 2016 rmarshall@redhat.com - 2.02-0.37 +- Update fix for rhbz#1212114 to reflect the move to handling this case + in anaconda. + Related: rhbz#1315468 + Resolves: rhbz#1261926 +- Add grub2-get-kernel-settings to allow grub2-mkconfig to take grubby + configuration changes into account. + Resolves: rhbz#1226325 + +* Fri Jun 17 2016 Peter Jones - 2.02-0.36 +- Better support for EFI network booting with dhcpv6. + Resolves: rhbz#1154226 +- Back out a duplicate change resulting in some EFI network firmware drivers + not working properly. + Related: rhbz#1273974 + Related: rhbz#1277599 + Related: rhbz#1298765 + +* Mon Jun 06 2016 Peter Jones - 2.02-0.35 +- Don't use legacy methods to make device node variables. + Resolves: rhbz#1279599 +- Don't pad initramfs with zeros + Resolves: rhbz#1219864 + +* Thu Apr 28 2016 rmarshall@redhat.com 2.02-0.34 +- Exit grub-mkconfig with a proper code when the new configuration would be + invalid. + Resolves: rhbz#1252311 +- Warn users if grub-mkconfig needs to be run to add support for GRUB + passwords. + Resolves: rhbz#1290803 +- Fix the information in the --help and man pages for grub-setpassword + Resolves: rhbz#1290799 +- Fix issue where shell substitution expected non-translated output when + setting a bootloader password. + Resolves: rhbz#1294243 +- Fix an issue causing memory regions with unknown types to be marked available + through a series of backports from upstream. + Resolves: rhbz#1288608 + +* Thu Dec 10 2015 Peter Jones - 2.02-0.33 +- Don't remove 01_users, it's the wrong thing to do. + Related: rhbz#1284370 + +* Wed Dec 09 2015 Peter Jones - 2.02-0.32 +- Rebuild for .z so the release number is different. + Related: rhbz#1284370 + +* Wed Dec 09 2015 Peter Jones - 2.02-0.31 +- More work on handling of GRUB2_PASSWORD + Resolves: rhbz#1284370 + +* Tue Dec 08 2015 Peter Jones - 2.02-0.30 +- Fix security issue when reading username and password + Resolves: CVE-2015-8370 +- Do a better job of handling GRUB_PASSWORD + Resolves: rhbz#1284370 + +* Fri Oct 09 2015 Peter Jones - 2.02-0.29 +- Fix DHCP6 timeouts due to failed network stack once more. + Resolves: rhbz#1267139 + +* Thu Sep 17 2015 Peter Jones - 2.02-0.28 +- Once again, rebuild for the right build target. + Resolves: CVE-2015-5281 + +* Thu Sep 17 2015 Peter Jones - 2.02-0.27 +- Remove multiboot and multiboot2 modules from the .efi builds; they + should never have been there. + Resolves: CVE-2015-5281 + +* Mon Sep 14 2015 Peter Jones - 2.02-0.26 +- Be more aggressive about trying to make sure we use the configured SNP + device in UEFI. + Resolves: rhbz#1257475 + +* Wed Aug 05 2015 Robert Marshall - 2.02-0.25 +- Force file sync to disk on ppc64le machines. + Resolves: rhbz#1212114 + +* Mon Aug 03 2015 Peter Jones - 2.02-0.24 +- Undo 0.23 and fix it a different way. + Resolves: rhbz#1124074 + +* Thu Jul 30 2015 Peter Jones - 2.02-0.23 +- Reverse kernel sort order so they're displayed correctly. + Resolves: rhbz#1124074 + +* Wed Jul 08 2015 Peter Jones - 2.02-0.22 +- Make upgrades work reasonably well with grub2-setpassword . + Related: rhbz#985962 + +* Tue Jul 07 2015 Peter Jones - 2.02-0.21 +- Add a simpler grub2 password config tool + Related: rhbz#985962 +- Some more coverity nits. + +* Mon Jul 06 2015 Peter Jones - 2.02-0.20 +- Deal with some coverity nits. + Related: rhbz#1215839 + Related: rhbz#1124074 + +* Mon Jul 06 2015 Peter Jones - 2.02-0.19 +- Rebuild for Aarch64 +- Deal with some coverity nits. + Related: rhbz#1215839 + Related: rhbz#1124074 + +* Thu Jul 02 2015 Peter Jones - 2.02-0.18 +- Update for an rpmdiff problem with one of the man pages. + Related: rhbz#1124074 + +* Tue Jun 30 2015 Peter Jones - 2.02-0.17 +- Handle ipv6 better + Resolves: rhbz#1154226 +- On UEFI, use SIMPLE_NETWORK_PROTOCOL when we can. + Resolves: rhbz#1233378 +- Handle rssd disk drives in grub2 utilities. + Resolves: rhbz#1087962 +- Handle xfs CRC disk format. + Resolves: rhbz#1001279 +- Calibrate TCS using the EFI Stall service + Resolves: rhbz#1150698 +- Fix built-in gpg verification when using TFTP + Resolves: rhbz#1167977 +- Generate better stanza titles so grubby can find them easier. + Resolves: rhbz#1177003 +- Don't strip the fw_path variable twice when we're using EFI networking. + Resolves: rhbz#1211101 + +* Mon May 11 2015 Peter Jones - 2.02-0.17 +- Document network boot paths better + Resolves: rhbz#1148650 +- Use an rpm-based version sorted in grub2-mkconfig + Resolves: rhbz#1124074 + +* Thu Oct 09 2014 Peter Jones - 2.02-0.16 +- ... and build it on the right target. + Related: rhbz#1148652 + +* Thu Oct 09 2014 Peter Jones - 2.02-0.15 +- Make netbooting do a better job of picking the config path *again*. + Resolves: rhbz#1148652 + +* Sat Oct 04 2014 Peter Jones - 2.02-0.14 +- Be sure to *install* gcdaa64.efi + Related: rhbz#1100048 + +* Fri Sep 26 2014 Peter Jones - 2.02-0.13 +- Make sure to build a gcdaa64.efi + Related: rhbz#1100048 + +* Tue Sep 23 2014 Peter Jones - 2.02-0.12 +- Fix minor problems rpmdiff found. + Related: rhbz#1125540 + +* Mon Sep 22 2014 Peter Jones - 2.02-0.11 +- Fix grub2 segfault when root isn't set. + Resolves: rhbz#1084536 +- Make the aarch64 loader be SB-aware. + Related: rhbz#1100048 +- Enable regexp module + Resolves: rhbz#1125916 + +* Thu Sep 04 2014 Peter Jones - 2.02-0.10 +- Make editenv utilities (grub2-editenv, grub2-set-default, etc.) from + non-UEFI builds work with UEFI builds as well, since they're shared + from grub2-tools. + Resolves: rhbz#1119943 +- Make more grub2-mkconfig generate menu entries with the OS name and version + included. + Resolves: rhbz#996794 +- Minimize the sort ordering for .debug and -rescue- kernels. + Resolves: rhbz#1065360 +- Add GRUB_DISABLE_UUID to disable filesystem searching by UUID. + Resolves: rhbz#1027833 +- Allow "fallback" to specify titles like the documentation says + Resolves: rhbz#1026084 + +* Wed Aug 27 2014 Peter Jones - 2.02-0.9.1 +- A couple of patches for aarch64 got missed. + Related: rhbz#967937 + +* Wed Aug 27 2014 Peter Jones - 2.02-0.9 +- Once again, I have built with the wrong target. + Related: rhbz#1125540 + Resolves: rhbz#967937 + +* Fri Aug 22 2014 Peter Jones - 2.02-0.8 +- Add patches for ppc64le + Related: rhbz#1125540 + +* Thu Mar 20 2014 Peter Jones - 2.02-0.2.10 +- Fix GRUB_DISABLE_SUBMENU one more time. + Resolves: rhbz#1063414 + +* Tue Mar 18 2014 Peter Jones - 2.02-0.2.9 +- Not sure why the right build target wasn't used *again*. + Resolves: rhbz#1073337 + +* Wed Mar 12 2014 Peter Jones - 2.02-0.2.8 +- Make GRUB_DISABLE_SUBMENU work again. + Resolves: rhbz#1063414 + +* Thu Mar 06 2014 Peter Jones - 2.02-0.2.7 +- Build on the right target. + Resolves: rhbz#1073337 + +* Wed Mar 05 2014 Peter Jones - 2.02-0.2.6 +- Fix minor man page install bug + Related: rhbz#948847 + +* Tue Mar 04 2014 Peter Jones - 2.02-0.2.5 +- Add man pages for common grub utilities. + Resolves: rhbz#948847 +- Fix shift key behavior on UEFI. + Resolves: rhbz#1068215 + +* Tue Feb 18 2014 Peter Jones - 2.02-0.2.4 +- Build against the right target. + Related: rhbz#1064424 + +* Tue Feb 18 2014 Peter Jones - 2.02-0.2.3 +- Don't emit "Booting " message. + Resolves: rhbz#1023142 +- Don't require a password for booting, only for editing entries. + Resolves: rhbz#1030176 +- Several network fixes from IBM + Resolves: rhbz#1056324 +- Support NVMe device names + Resolves: rhbz#1019660 +- Make control keys work on UEFI systems. + Resolves: rhbz#1056035 + +* Fri Jan 31 2014 Peter Jones - 2.02-0.2.2 +- Fix FORTIFY_SOURCE for util/ + Related: rhbz#1049047 + +* Tue Jan 21 2014 Peter Jones - 2.02-0.2.1 +- Don't destroy symlinks when re-writing grub.cfg + Resolves: rhbz#1032182 + +* Mon Jan 06 2014 Peter Jones - 2.02-0.2 +- Update to grub-2.02~beta2 + +* Fri Dec 27 2013 Daniel Mach - 1:2.00-23 +- Mass rebuild 2013-12-27 + +* Wed Nov 20 2013 Peter Jones - 2.00-22.10 +- Rebuild with correct release number and with correct target. + Related: rhbz#1032530 + +* Wed Nov 20 2013 Daniel Mach - 2.00-22.9.1 +- Enable tftp module + Resolves: rhbz#1032530 + +* Thu Nov 14 2013 Peter Jones - 2.00-22.9 +- Make "linux16" happen on x86_64 machines as well. + Resolves: rhbz#880840 + +* Wed Nov 06 2013 Peter Jones - 2.00-22.8 +- Rebuild with correct build target for signing. + Related: rhbz#996863 + +* Tue Nov 05 2013 Peter Jones - 2.00-22.7 +- Build with -mcpu=power6 as we did before redhat-rpm-config changed + Resolves: rhbz#1026368 + +* Thu Oct 31 2013 Peter Jones - 2.00-22.6 +- Make linux16 work with the shell better. + Resolves: rhbz#880840 + +* Thu Oct 31 2013 Peter Jones - 2.00-22.5 +- Rebuild because we were clobbering signing in the spec file... + Related: rhbz#1017855 + +* Thu Oct 31 2013 Peter Jones - 2.00-22.4 +- Rebuild because signing didn't work. + Related: rhbz#1017855 + +* Mon Oct 28 2013 Peter Jones - 2.00-22.3 +- Use linux16 when appropriate: + Resolves: rhbz#880840 +- Enable pager by default: + Resolves: rhbz#985860 +- Don't ask the user to hit keys that won't work. + Resolves: rhbz#987443 +- Sign grub2 during builds + Resolves: rhbz#1017855 + +* Thu Aug 29 2013 Peter Jones - 2.00-22.2 +- Fix minor rpmdiff complaints. + +* Wed Aug 07 2013 Peter Jones - 2.00-22.1 +- Fix url so PkgWrangler doesn't go crazy. + +* Fri Jun 21 2013 Peter Jones - 2.00-22 +- Fix linewrapping in edit menu. + Resolves: rhbz #976643 + +* Thu Jun 20 2013 Peter Jones - 2.00-21 +- Fix obsoletes to pull in -starfield-theme subpackage when it should. + +* Fri Jun 14 2013 Peter Jones - 2.00-20 +- Put the theme entirely ento the subpackage where it belongs (#974667) + +* Wed Jun 12 2013 Peter Jones - 2.00-19 +- Rebase to upstream snapshot. +- Fix PPC build error (#967862) +- Fix crash on net_bootp command (#960624) +- Reset colors on ppc when appropriate (#908519) +- Left align "Loading..." messages (#908492) +- Fix probing of SAS disks on PPC (#953954) +- Add support for UEFI OSes returned by os-prober +- Disable "video" mode on PPC for now (#973205) +- Make grub fit better into the boot sequence, visually (#966719) + +* Fri May 10 2013 Matthias Clasen - 2.00-18 +- Move the starfield theme to a subpackage (#962004) +- Don't allow SSE or MMX on UEFI builds (#949761) + +* Wed Apr 24 2013 Peter Jones - 2.00-17.pj0 +- Rebase to upstream snapshot. + +* Thu Apr 04 2013 Peter Jones - 2.00-17 +- Fix booting from drives with 4k sectors on UEFI. +- Move bash completion to new location (#922997) +- Include lvm support for /boot (#906203) + +* Thu Feb 14 2013 Peter Jones - 2.00-16 +- Allow the user to disable submenu generation +- (partially) support BLS-style configuration stanzas. + +* Tue Feb 12 2013 Peter Jones - 2.00-15.pj0 +- Add various config file related changes. + +* Thu Dec 20 2012 Dennis Gilmore - 2.00-15 +- bump nvr + +* Mon Dec 17 2012 Karsten Hopp 2.00-14 +- add bootpath device to the device list (pfsmorigo, #886685) + +* Tue Nov 27 2012 Peter Jones - 2.00-13 +- Add vlan tag support (pfsmorigo, #871563) +- Follow symlinks during PReP installation in grub2-install (pfsmorigo, #874234) +- Improve search paths for config files on network boot (pfsmorigo, #873406) + +* Tue Oct 23 2012 Peter Jones - 2.00-12 +- Don't load modules when grub transitions to "normal" mode on UEFI. + +* Mon Oct 22 2012 Peter Jones - 2.00-11 +- Rebuild with newer pesign so we'll get signed with the final signing keys. + +* Thu Oct 18 2012 Peter Jones - 2.00-10 +- Various PPC fixes. +- Fix crash fetching from http (gustavold, #860834) +- Issue separate dns queries for ipv4 and ipv6 (gustavold, #860829) +- Support IBM CAS reboot (pfsmorigo, #859223) +- Include all modules in the core image on ppc (pfsmorigo, #866559) + +* Mon Oct 01 2012 Peter Jones - 1:2.00-9 +- Work around bug with using "\x20" in linux command line. + Related: rhbz#855849 + +* Thu Sep 20 2012 Peter Jones - 2.00-8 +- Don't error on insmod on UEFI/SB, but also don't do any insmodding. +- Increase device path size for ieee1275 + Resolves: rhbz#857936 +- Make network booting work on ieee1275 machines. + Resolves: rhbz#857936 + +* Wed Sep 05 2012 Matthew Garrett - 2.00-7 +- Add Apple partition map support for EFI + +* Thu Aug 23 2012 David Cantrell - 2.00-6 +- Only require pesign on EFI architectures (#851215) + +* Tue Aug 14 2012 Peter Jones - 2.00-5 +- Work around AHCI firmware bug in efidisk driver. +- Move to newer pesign macros +- Don't allow insmod if we're in secure-boot mode. + +* Wed Aug 08 2012 Peter Jones +- Split module lists for UEFI boot vs UEFI cd images. +- Add raid modules for UEFI image (related: #750794) +- Include a prelink whitelist for binaries that need execstack (#839813) +- Include fix efi memory map fix from upstream (#839363) + +* Wed Aug 08 2012 Peter Jones - 2.00-4 +- Correct grub-mkimage invocation to use efidir RPM macro (jwb) +- Sign with test keys on UEFI systems. +- PPC - Handle device paths with commas correctly. + Related: rhbz#828740 + +* Wed Jul 25 2012 Peter Jones - 2.00-3 +- Add some more code to support Secure Boot, and temporarily disable + some other bits that don't work well enough yet. + Resolves: rhbz#836695 + +* Wed Jul 11 2012 Matthew Garrett - 2.00-2 +- Set a prefix for the image - needed for installer work +- Provide the font in the EFI directory for the same reason + +* Thu Jun 28 2012 Peter Jones - 2.00-1 +- Rebase to grub-2.00 release. + +* Mon Jun 18 2012 Peter Jones - 2.0-0.37.beta6 +- Fix double-free in grub-probe. + +* Wed Jun 06 2012 Peter Jones - 2.0-0.36.beta6 +- Build with patch19 applied. + +* Wed Jun 06 2012 Peter Jones - 2.0-0.35.beta6 +- More ppc fixes. + +* Wed Jun 06 2012 Peter Jones - 2.0-0.34.beta6 +- Add IBM PPC fixes. + +* Mon Jun 04 2012 Peter Jones - 2.0-0.33.beta6 +- Update to beta6. +- Various fixes from mads. + +* Fri May 25 2012 Peter Jones - 2.0-0.32.beta5 +- Revert builddep change for crt1.o; it breaks ppc build. + +* Fri May 25 2012 Peter Jones - 2.0-0.31.beta5 +- Add fwsetup command (pjones) +- More ppc fixes (IBM) + +* Tue May 22 2012 Peter Jones - 2.0-0.30.beta5 +- Fix the /other/ grub2-tools require to include epoch. + +* Mon May 21 2012 Peter Jones - 2.0-0.29.beta5 +- Get rid of efi_uga and efi_gop, favoring all_video instead. + +* Mon May 21 2012 Peter Jones - 2.0-0.28.beta5 +- Name grub.efi something that's arch-appropriate (kiilerix, pjones) +- use EFI/$SOMETHING_DISTRO_BASED/ not always EFI/redhat/grub2-efi/ . +- move common stuff to -tools (kiilerix) +- spec file cleanups (kiilerix) + +* Mon May 14 2012 Peter Jones - 2.0-0.27.beta5 +- Fix module trampolining on ppc (benh) + +* Thu May 10 2012 Peter Jones - 2.0-0.27.beta5 +- Fix license of theme (mizmo) + Resolves: rhbz#820713 +- Fix some PPC bootloader detection IBM problem + Resolves: rhbz#820722 + +* Thu May 10 2012 Peter Jones - 2.0-0.26.beta5 +- Update to beta5. +- Update how efi building works (kiilerix) +- Fix theme support to bring in fonts correctly (kiilerix, pjones) + +* Wed May 09 2012 Peter Jones - 2.0-0.25.beta4 +- Include theme support (mizmo) +- Include locale support (kiilerix) +- Include html docs (kiilerix) + +* Thu Apr 26 2012 Peter Jones - 2.0-0.24 +- Various fixes from Mads Kiilerich + +* Thu Apr 19 2012 Peter Jones - 2.0-0.23 +- Update to 2.00~beta4 +- Make fonts work so we can do graphics reasonably + +* Thu Mar 29 2012 David Aquilina - 2.0-0.22 +- Fix ieee1275 platform define for ppc + +* Thu Mar 29 2012 Peter Jones - 2.0-0.21 +- Remove ppc excludearch lines (dwa) +- Update ppc terminfo patch (hamzy) + +* Wed Mar 28 2012 Peter Jones - 2.0-0.20 +- Fix ppc64 vs ppc exclude according to what dwa tells me they need +- Fix version number to better match policy. + +* Tue Mar 27 2012 Dan Horák - 1.99-19.2 +- Add support for serial terminal consoles on PPC by Mark Hamzy + +* Sun Mar 25 2012 Dan Horák - 1.99-19.1 +- Use Fix-tests-of-zeroed-partition patch by Mark Hamzy + +* Thu Mar 15 2012 Peter Jones - 1.99-19 +- Use --with-grubdir= on configure to make it behave like -17 did. + +* Wed Mar 14 2012 Peter Jones - 1.99-18 +- Rebase from 1.99 to 2.00~beta2 + +* Wed Mar 07 2012 Peter Jones - 1.99-17 +- Update for newer autotools and gcc 4.7.0 + Related: rhbz#782144 +- Add /etc/sysconfig/grub link to /etc/default/grub + Resolves: rhbz#800152 +- ExcludeArch s390*, which is not supported by this package. + Resolves: rhbz#758333 + +* Fri Feb 17 2012 Orion Poplawski - 1:1.99-16 +- Build with -Os (bug 782144) + +* Fri Jan 13 2012 Fedora Release Engineering - 1:1.99-15 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Wed Dec 14 2011 Matthew Garrett - 1.99-14 +- fix up various grub2-efi issues + +* Thu Dec 08 2011 Adam Williamson - 1.99-13 +- fix hardwired call to grub-probe in 30_os-prober (rhbz#737203) + +* Mon Nov 07 2011 Peter Jones - 1.99-12 +- Lots of .spec fixes from Mads Kiilerich: + Remove comment about update-grub - it isn't run in any scriptlets + patch info pages so they can be installed and removed correctly when renamed + fix references to grub/grub2 renames in info pages (#743964) + update README.Fedora (#734090) + fix comments for the hack for upgrading from grub2 < 1.99-4 + fix sed syntax error preventing use of $RPM_OPT_FLAGS (#704820) + make /etc/grub2*.cfg %config(noreplace) + make grub.cfg %ghost - an empty file is of no use anyway + create /etc/default/grub more like anaconda would create it (#678453) + don't create rescue entries by default - grubby will not maintain them anyway + set GRUB_SAVEDEFAULT=true so saved defaults works (rbhz#732058) + grub2-efi should have its own bash completion + don't set gfxpayload in efi mode - backport upstream r3402 +- Handle dmraid better. Resolves: rhbz#742226 + +* Wed Oct 26 2011 Fedora Release Engineering - 1:1.99-11 +- Rebuilt for glibc bug#747377 + +* Wed Oct 19 2011 Adam Williamson - 1.99-10 +- /etc/default/grub is explicitly intended for user customization, so + mark it as config(noreplace) + +* Tue Oct 11 2011 Peter Jones - 1.99-9 +- grub has an epoch, so we need that expressed in the obsolete as well. + Today isn't my day. + +* Tue Oct 11 2011 Peter Jones - 1.99-8 +- Fix my bad obsoletes syntax. + +* Thu Oct 06 2011 Peter Jones - 1.99-7 +- Obsolete grub + Resolves: rhbz#743381 + +* Wed Sep 14 2011 Peter Jones - 1.99-6 +- Use mv not cp to try to avoid moving disk blocks around for -5 fix + Related: rhbz#735259 +- handle initramfs on xen better (patch from Marko Ristola) + Resolves: rhbz#728775 + +* Sat Sep 03 2011 Kalev Lember - 1.99-5 +- Fix upgrades from grub2 < 1.99-4 (#735259) + +* Fri Sep 02 2011 Peter Jones - 1.99-4 +- Don't do sysadminny things in %preun or %post ever. (#735259) +- Actually include the changelog in this build (sorry about -3) + +* Thu Sep 01 2011 Peter Jones - 1.99-2 +- Require os-prober (#678456) (patch from Elad Alfassa) +- Require which (#734959) (patch from Elad Alfassa) + +* Thu Sep 01 2011 Peter Jones - 1.99-1 +- Update to grub-1.99 final. +- Fix crt1.o require on x86-64 (fix from Mads Kiilerich) +- Various CFLAGS fixes (from Mads Kiilerich) + - -fexceptions and -m64 +- Temporarily ignore translations (from Mads Kiilerich) + +* Thu Jul 21 2011 Peter Jones - 1.99-0.3 +- Use /sbin not /usr/sbin . + +* Thu Jun 23 2011 Peter Lemenkov - 1:1.99-0.2 +- Fixes for ppc and ppc64 + +* Wed Feb 09 2011 Fedora Release Engineering - 1:1.98-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild