diff --git a/ChangeLog b/ChangeLog-2015
similarity index 99%
rename from ChangeLog
rename to ChangeLog-2015
index 6fbec061d..869f6bfb8 100644
--- a/ChangeLog
+++ b/ChangeLog-2015
@@ -1,3 +1,259 @@
+2015-01-23  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* tests/file_filter/file: Really add missing file.
+
+2015-01-23  Andrei Borzenkov  <arvidjaar@gmail.com>
+
+	* grub-core/disk/xen/xendisk.c: Accept hdX as disk names on Xen to
+	allow legacy menu.lst processing.
+
+2015-01-22  Felix Janda <felix.janda@posteo.de>
+
+	Remove direct _llseek code and require long filesystem libc.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	Remove potential division by 0 in gfxmenu.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/normal/menu_text.c (grub_menu_init_page): Avoid
+	returning 0 geometry to avoid divisions by 0.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/osdep/unix/cputime.c (grub_util_get_cpu_time_ms): Cache
+	sc_clk_tck and check it for sanity.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/kern/efi/mm.c (grub_efi_get_memory_map): Never return a
+	descriptor_size==0 to avoid potential divisions by zero.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/osdep/haiku/getroot.c (grub_util_find_partition_start_os):
+	Avoid division by zero.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/kern/generic/rtc_get_time_ms.c (grub_rtc_get_time_ms): Avoid
+	division by zero.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/loader/i386/xnu.c (guessfsb): Avoid division by 0.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/kern/i386/tsc.c (calibrate_tsc): Ensure that
+	no division by 0 occurs.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* include/grub/misc.h (grub_div_roundup): Remove as it's unused.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/term/gfxterm.c: Avoid division by zero.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	Avoid division by zero in serial.
+
+	* grub-core/term/serial.c (grub_cmd_serial): Ensure speed is not 0.
+	* grub-core/term/ns8250.c (serial_get_divisor): Exit if speed is 0.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/video/readers/jpeg.c: Avoid sivision by zero.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/disk/diskfilter.c: Validate volumes to avoid division
+	by zero.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* include/grub/term.h: Avoid returining 0-sized terminal
+	as it may lead to division by zero.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/fs/zfs.c: Avoid divisions by zero.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/fs/btrfs.c: Avoid divisions by zero.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/lib/pbkdf2.c (grub_crypto_pbkdf2): Check that hash len is not 0.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/osdep/linux/blocklist.c (grub_install_get_blocklist): Check
+	blocksize validity.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/disk/i386/pc/biosdisk.c: Check disk size sanity.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/disk/ieee1275/nand.c (grub_nand_open): Check block size
+	validity.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/disk/dmraid_nvidia.c (grub_dmraid_nv_detect): Do not
+	divide by zero.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/fs/hfs.c (grub_hfs_mount): Additional filesystem
+	sanity checks.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/fs/minix.c: Additional filesystem
+	sanity checks.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/fs/ext2.c (grub_ext2_mount): Additional
+	checks for superblock validity.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/fs/ufs.c (grub_ufs_mount): Check
+	that sblock.ino_per_group is not 0.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	Reject NILFS2 superblocks with over 1GiB blocks.
+
+	* grub-core/fs/nilfs2.c (grub_nilfs2_valid_sb): Check that
+	block size is <= 1GiB.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/disk/ata.c (grub_ata_setaddress): Check that geometry
+	is sane when using CHS addressing.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/disk/AFSplitter.c (AF_merge): Check that mdlen is not 0.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/commands/i386/pc/play.c (grub_cmd_play): Avoid
+	division by zero.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/bus/usb/usbtrans.c (grub_usb_bulk_maxpacket): Avoid
+	potentially returning 0.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/fs/minix.c (grub_minix_read_file): Avoid reading past
+	the end of file.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/fs/fshelp.c (grub_fshelp_read_file): Don't attempt to read
+	past the end of file.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	* grub-core/script/lexer.c (grub_script_lexer_yywrap): Update len
+	synchronously with line.
+
+2015-01-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+	Replace explicit sizeof divisions by ARRAY_SIZE.
+
+2015-01-19  Kris Moore <kris@pcbsd.org>
+
+	* grub-core/disk/geli.c: Support GELI v6 and v7.
+
+2014-12-09  Andrei Borzenkov  <arvidjaar@gmail.com>
+
+	* grub-core/term/serial.c (grub_cmd_serial): Fix --rtscts
+	option processing.
+
+2014-12-07  David Kozub  <zub.272@gmail.com>
+
+	* grub-core/kern/arm/misc.S: fix unaligned 64bit local variable
+	in __aeabi_uidivmod
+	Fixes Savannah bug #43632.
+
+2014-12-07  Peter Nelson <peterdn>
+
+	* grub-core/fs/ext2.c (grub_ext2_read_block): Support large sparse
+	chunks.
+
+2014-12-07  Andrei Borzenkov  <arvidjaar@gmail.com>
+
+	* util/grub-mkconfig_lib.in (version_test_gt): Remove redundant
+	non-portable '-n' echo option.
+	* util/grub.d/10_kfreebsd.in: Change how list is built to avoid
+	non-portable 'echo -n.
+	* util/grub.d/10_linux.in: Likewise (closes 43668).
+	* util/grub.d/20_linux_xen.in: Likewise.
+	* util/grub.d/30_os-prober.in: Print spaces directly to avoid
+	non-portable 'echo -n'.
+
+2014-12-07  Curtis Larsen <larsen@dixie.edu>
+
+	* grub-core/net/tcp.c (grub_net_recv_tcp_packet): Fix double
+	free when multiple empty segments were received (closes 42765).
+
+2014-12-05  Andrei Borzenkov  <arvidjaar@gmail.com>
+
+	* tests/util/grub-shell.in: Support --files also for netboot.
+	* tests/file_filter_test.in: New file with file filters tests.
+	* Makefile.util.def: Add file_filter_test.
+	* conf/Makefile.extra-dist: ... and here.
+	* tests/file_filter/file.gz: Test file for file_filter_test.
+	* tests/file_filter/file.gz.sig: Likewise.
+	* tests/file_filter/file.lzop: Likewise.
+	* tests/file_filter/file.lzop.sig: Likewise.
+	* tests/file_filter/file.xz: Likewise.
+	* tests/file_filter/file.xz.sig: Likewise.
+	* tests/file_filter/keys: Likewise.
+	* tests/file_filter/keys.pub: Likewise.
+	* tests/file_filter/test.cfg: Likewise.
+	* grub-core/commands/verify.c: Fix memory corruption doing
+	signature check for network files (closes 43601).
+
+2014-12-01  Andrei Borzenkov  <arvidjaar@gmail.com>
+
+	* grub-core/loader/i386/xen_fileXX.c (grub_xen_get_infoXX): Fix
+	memory leak (CID 73645, 73782).
+	* grub-core/fs/zfs/zfsinfo.c (print_vdev_info): Fix memory leak
+	(CID 73635).
+
+2014-11-30  Andrei Borzenkov  <arvidjaar@gmail.com>
+
+	* grub-core/lib/syslinux_parse.c (free_menu): Do not free
+	inline array (CID 73610).
+
+2014-11-28  Andrei Borzenkov  <arvidjaar@gmail.com>
+
+	* grub-core/io/lzopio.c (test_header): Fix double free (CID 73665)
+	* grub-core/disk/geli.c (configure_ciphers): Fix memory leaks
+	(Coverity CID 73813, 73710)
+	* grub-core/disk/luks.c (configure_ciphers): Fix memory leaks
+	and use after free (Coverity CID 73813, 73710, 73730)
+	* grub-core/disk/luks.c (luks_recover_key): Fix memory leak (Coverity
+	CID 73854)
+	* util/grub-install-common.c (grub_install_get_target): Check return
+	value of grub_util_fd_read (Coverity CID 73819).
+	* util/grub-mkstandalone.c (add_tar_file): Fix out of bound access
+	to hd.magic (Coverity CID 73587, 73888, bug 43690).
+
 2014-11-20  Andrei Borzenkov  <arvidjaar@gmail.com>
 
 	* tests/util/grub-fs-tester.in: Consistently print output
diff --git a/INSTALL b/INSTALL
index b67cd7f34..e5b081105 100644
--- a/INSTALL
+++ b/INSTALL
@@ -13,6 +13,9 @@ configuring the GRUB.
 
 * GCC 4.1.3 or later
   Note: older versions may work but support is limited
+
+  Experimental support for clang 3.3 or later (results in much bigger binaries)
+  for i386, x86_64, arm (except thumb), arm64, mips(el), powerpc, sparc64
   Note: clang 3.2 or later works for i386 and x86_64 targets but results in
         much bigger binaries.
 	earlier versions not tested
@@ -26,7 +29,8 @@ configuring the GRUB.
 	fail.
   Note: clang 3.2 or later works for powerpc
 	earlier versions not tested
-  Note: clang doesn't support -mno-app-regs and so can't be used for sparc64
+  Note: clang 3.5 or later works for sparc64
+        earlier versions return "error: unable to interface with target machine"
   Note: clang has no support for ia64 and hence you can't compile GRUB
 	for ia64 with clang
 * GNU Make
@@ -35,6 +39,7 @@ configuring the GRUB.
 * GNU binutils 2.9.1.0.23 or later
 * Flex 2.5.35 or later
 * Other standard GNU/Unix tools
+* a libc with large file support (e.g. glibc 2.1 or later)
 
 On GNU/Linux, you also need:
 
@@ -99,6 +104,9 @@ The simplest way to compile this package is:
   
   3. Type `./autogen.sh'.
 
+     * autogen.sh uses python. By default invocation is "python" but can be
+       overriden by setting variable $PYTHON.
+
   4. Type `./configure' to configure the package for your system.
      If you're using `csh' on an old version of System V, you might
      need to type `sh ./configure' instead to prevent `csh' from trying
@@ -174,9 +182,9 @@ corresponding platform are not needed for the platform in question.
   - For host
     1. --host= to autoconf name of host.
     2. CC= for gcc able to compile for host
-    3. CFLAGS= for C options for host.
-    4. CPPFLAGS= for C preprocessor options for host.
-    5. LDFLAGS= for linker options for host.
+    3. HOST_CFLAGS= for C options for host.
+    4. HOST_CPPFLAGS= for C preprocessor options for host.
+    5. HOST_LDFLAGS= for linker options for host.
     6. FREETYPE= for freetype-config for host (optional).
     7. Libdevmapper if any must be in standard linker folders (-ldevmapper) (optional).
     8. Libfuse if any must be in standard linker folders (-lfuse) (optional).
diff --git a/Makefile.am b/Makefile.am
index cc537a2c8..994ebbd39 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -392,7 +392,7 @@ endif
 .PHONY: bootcheck-linux-i386 bootcheck-linux-x86_64 \
        bootcheck-kfreebsd-i386 bootcheck-kfreebsd-x86_64 \
        bootcheck-knetbsd-i386 bootcheck-knetbsd-x86_64 \
-	bootcheck-linux-mips
+	bootcheck-linux-mips FORCE
 
 # Randomly generated
 SUCCESSFUL_BOOT_STRING=3e49994fd5d82b7c9298d672d774080d
@@ -439,3 +439,22 @@ windowszip: windowsdir
 	rm -rf $(windowsdir)
 
 EXTRA_DIST += linguas.sh
+
+changelog_start_date = 2015-01-23
+gitlog_to_changelog = $(top_srcdir)/build-aux/gitlog-to-changelog
+
+ChangeLog: FORCE
+	if test -d $(top_srcdir)/.git; then \
+		$(gitlog_to_changelog) --srcdir=$(top_srcdir) --since=$(changelog_start_date) > '$@.tmp'; \
+		rm -f '$@'; mv '$@.tmp' '$@'; \
+	else \
+		touch $@; \
+	fi
+
+EXTRA_DIST += ChangeLog ChangeLog-2015
+
+syslinux_test: $(top_builddir)/config.status tests/syslinux/ubuntu10.04_grub.cfg
+
+tests/syslinux/ubuntu10.04_grub.cfg: $(top_builddir)/config.status tests/syslinux/ubuntu10.04_grub.cfg.in
+	(for x in tests/syslinux/ubuntu10.04_grub.cfg.in ; do cat $(srcdir)/"$$x"; done) | $(top_builddir)/config.status --file=$@:-
+CLEANFILES += tests/syslinux/ubuntu10.04_grub.cfg
diff --git a/Makefile.util.def b/Makefile.util.def
index a2b3e30de..5d8d1f031 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -613,7 +613,6 @@ program = {
   common = grub-core/disk/host.c;
 
   common = util/resolve.c;
-  enable = noemu;
   common = grub-core/kern/emu/argp_common.c;
   common = grub-core/osdep/init.c;
 
@@ -1162,6 +1161,24 @@ script = {
   common = tests/gptprio_test.in;
 };
 
+script = {
+  testcase;
+  name = file_filter_test;
+  common = tests/file_filter_test.in;
+};
+
+script = {
+  testcase;
+  name = grub_cmd_test;
+  common = tests/grub_cmd_test.in;
+};
+
+script = {
+  testcase;
+  name = syslinux_test;
+  common = tests/syslinux_test.in;
+};
+
 program = {
   testcase;
   name = example_unit_test;
diff --git a/NEWS b/NEWS
index a61df942a..e417ebad1 100644
--- a/NEWS
+++ b/NEWS
@@ -85,6 +85,8 @@ New in 2.02:
   * Support for USB debug dongles.
   * Support for *-emu on all platforms (previously only i386/x86_64 worked).
   * Support *-emu on Windows.
+  * New platform `none' which builds only user level utilities. This is now
+    default if target CPU is not supported.
 
 * Security:
   * Add optional facility to enforce that all files read by the core image
diff --git a/acinclude.m4 b/acinclude.m4
index b2bb88d83..609c4f2f6 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -210,80 +210,6 @@ fi
 ])
 
 
-dnl Mass confusion!
-dnl Older versions of GAS interpret `.code16' to mean ``generate 32-bit
-dnl instructions, but implicitly insert addr32 and data32 bytes so
-dnl that the code works in real mode''.
-dnl
-dnl Newer versions of GAS interpret `.code16' to mean ``generate 16-bit
-dnl instructions,'' which seems right.  This requires the programmer
-dnl to explicitly insert addr32 and data32 instructions when they want
-dnl them.
-dnl
-dnl We only support the newer versions, because the old versions cause
-dnl major pain, by requiring manual assembly to get 16-bit instructions into
-dnl asm files.
-AC_DEFUN([grub_I386_ASM_ADDR32],
-[AC_REQUIRE([AC_PROG_CC])
-AC_REQUIRE([grub_I386_ASM_PREFIX_REQUIREMENT])
-AC_MSG_CHECKING([for .code16 addr32 assembler support])
-AC_CACHE_VAL(grub_cv_i386_asm_addr32,
-[cat > conftest.s.in <<\EOF
-	.code16
-l1:	@ADDR32@	movb	%al, l1
-EOF
-
-if test "x$grub_cv_i386_asm_prefix_requirement" = xyes; then
-  sed -e s/@ADDR32@/addr32/ < conftest.s.in > conftest.s
-else
-  sed -e s/@ADDR32@/addr32\;/ < conftest.s.in > conftest.s
-fi
-
-if AC_TRY_COMMAND([${CC-cc} ${TARGET_CCASFLAGS} ${CFLAGS} -c conftest.s]) && test -s conftest.o; then
-  grub_cv_i386_asm_addr32=yes
-else
-  grub_cv_i386_asm_addr32=no
-fi
-
-rm -f conftest*])
-
-AC_MSG_RESULT([$grub_cv_i386_asm_addr32])])
-
-dnl Later versions of GAS requires that addr32 and data32 prefixes
-dnl appear in the same lines as the instructions they modify, while
-dnl earlier versions requires that they appear in separate lines.
-AC_DEFUN([grub_I386_ASM_PREFIX_REQUIREMENT],
-[AC_REQUIRE([AC_PROG_CC])
-AC_MSG_CHECKING(dnl
-[whether addr32 must be in the same line as the instruction])
-AC_CACHE_VAL(grub_cv_i386_asm_prefix_requirement,
-[cat > conftest.s <<\EOF
-	.code16
-l1:	addr32	movb	%al, l1
-EOF
-
-if AC_TRY_COMMAND([${CC-cc} ${TARGET_CCASFLAGS} ${CFLAGS} -c conftest.s]) && test -s conftest.o; then
-  grub_cv_i386_asm_prefix_requirement=yes
-else
-  grub_cv_i386_asm_prefix_requirement=no
-fi
-
-rm -f conftest*])
-
-if test "x$grub_cv_i386_asm_prefix_requirement" = xyes; then
-  grub_tmp_addr32="addr32"
-  grub_tmp_data32="data32"
-else
-  grub_tmp_addr32="addr32;"
-  grub_tmp_data32="data32;"
-fi
-
-ADDR32=$grub_tmp_addr32
-DATA32=$grub_tmp_data32
-
-AC_MSG_RESULT([$grub_cv_i386_asm_prefix_requirement])])
-
-
 dnl Check what symbol is defined as a bss start symbol.
 dnl Written by Michael Hohmoth and Yoshinori K. Okuji.
 AC_DEFUN([grub_CHECK_BSS_START_SYMBOL],
diff --git a/asm-tests/arm.S b/asm-tests/arm.S
new file mode 100644
index 000000000..97c2546bf
--- /dev/null
+++ b/asm-tests/arm.S
@@ -0,0 +1,20 @@
+/* on arm clang doesn't support .arch directive */
+
+	.text
+	.syntax	unified
+
+#if !defined (__thumb2__)
+	.arch	armv7a
+	.arm
+#else
+	.arch	armv7
+	.thumb
+#endif
+	mcr	p15, 0, r11, c7, c14, 2
+
+	/* clang restricts access to dsb/isb despite .arch  */
+	dsb
+	isb
+
+
+	
diff --git a/asm-tests/i386-pc.S b/asm-tests/i386-pc.S
new file mode 100644
index 000000000..97cd32ae8
--- /dev/null
+++ b/asm-tests/i386-pc.S
@@ -0,0 +1,10 @@
+/* on x86 old clang doesn't support .code16
+   newer clang supports it but creates 6-byte jumps instead of 3-byte ones
+   which makes us go over boot sector size.  */
+
+	.code16
+	jmp far
+	.org 4
+	.space 300
+far:
+	.byte 0
diff --git a/asm-tests/i386.S b/asm-tests/i386.S
new file mode 100644
index 000000000..30adc4fe2
--- /dev/null
+++ b/asm-tests/i386.S
@@ -0,0 +1,4 @@
+/* on x86 old clang doesn't support .code16  */
+
+	.code16
+	movb %al, %bl
diff --git a/asm-tests/mips.S b/asm-tests/mips.S
new file mode 100644
index 000000000..8233dfcc9
--- /dev/null
+++ b/asm-tests/mips.S
@@ -0,0 +1,11 @@
+/* on mips clang doesn't support privilegied instructions, doubleword store/load
+   and crashes with hand-written assembly
+ */
+
+	.set mips3
+	sync
+	ld $t2, 0($t6)
+
+a:
+	addiu $t7, $s0, (b - a)
+b:	nop
diff --git a/asm-tests/powerpc.S b/asm-tests/powerpc.S
new file mode 100644
index 000000000..396a6cce9
--- /dev/null
+++ b/asm-tests/powerpc.S
@@ -0,0 +1,8 @@
+/* clang <= 3.3 doesn't handle most of ppc assembly, not even inline assembly
+   used by gcrypt */
+/* Cache invalidation loop is a fair test.  */
+	li 5, 0
+1:	icbi 5, 3
+	addi 5, 5, 32
+	cmpw 5, 4
+	blt 1b
diff --git a/asm-tests/sparc64.S b/asm-tests/sparc64.S
new file mode 100644
index 000000000..03c5fe02a
--- /dev/null
+++ b/asm-tests/sparc64.S
@@ -0,0 +1,9 @@
+        .text
+1:	
+	/* A small list of examples of what clang doesn't support.  */
+	clr	%o0
+	lduw	[%o4 + 4], %o4
+	and     %o6, ~0xff, %o6
+	stw	%o5, [%o3]
+	bne,pt	%icc, 1b
+	 nop
diff --git a/autogen.sh b/autogen.sh
index 7424428d6..5020456bc 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -2,6 +2,9 @@
 
 set -e
 
+# Set ${PYTHON} to plain 'python' if not set already
+: ${PYTHON:=python}
+
 export LC_COLLATE=C
 unset LC_ALL
 
@@ -9,10 +12,10 @@ find . -iname '*.[ch]' ! -ipath './grub-core/lib/libgcrypt-grub/*' ! -ipath './b
 find util -iname '*.in' ! -name Makefile.in  |sort > po/POTFILES-shell.in
 
 echo "Importing unicode..."
-python util/import_unicode.py unicode/UnicodeData.txt unicode/BidiMirroring.txt unicode/ArabicShaping.txt grub-core/unidata.c
+${PYTHON} util/import_unicode.py unicode/UnicodeData.txt unicode/BidiMirroring.txt unicode/ArabicShaping.txt grub-core/unidata.c
 
 echo "Importing libgcrypt..."
-python util/import_gcry.py grub-core/lib/libgcrypt/ grub-core
+${PYTHON} util/import_gcry.py grub-core/lib/libgcrypt/ grub-core
 sed -n -f util/import_gcrypth.sed < grub-core/lib/libgcrypt/src/gcrypt.h.in > include/grub/gcrypt/gcrypt.h
 if [ -f include/grub/gcrypt/g10lib.h ]; then
     rm include/grub/gcrypt/g10lib.h
@@ -54,8 +57,8 @@ for extra in contrib/*/Makefile.core.def; do
   fi
 done
 
-python gentpl.py $UTIL_DEFS > Makefile.util.am
-python gentpl.py $CORE_DEFS > grub-core/Makefile.core.am
+${PYTHON} gentpl.py $UTIL_DEFS > Makefile.util.am
+${PYTHON} gentpl.py $CORE_DEFS > grub-core/Makefile.core.am
 
 for extra in contrib/*/Makefile.common; do
   if test -e "$extra"; then
diff --git a/build-aux/gitlog-to-changelog b/build-aux/gitlog-to-changelog
new file mode 100755
index 000000000..78afff4e8
--- /dev/null
+++ b/build-aux/gitlog-to-changelog
@@ -0,0 +1,432 @@
+eval '(exit $?0)' && eval 'exec perl -wS "$0" ${1+"$@"}'
+  & eval 'exec perl -wS "$0" $argv:q'
+    if 0;
+# Convert git log output to ChangeLog format.
+
+my $VERSION = '2012-07-29 06:11'; # UTC
+# The definition above must lie within the first 8 lines in order
+# for the Emacs time-stamp write hook (at end) to update it.
+# If you change this file with Emacs, please let the write hook
+# do its job.  Otherwise, update this string manually.
+
+# Copyright (C) 2008-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 <http://www.gnu.org/licenses/>.
+
+# Written by Jim Meyering
+
+use strict;
+use warnings;
+use Getopt::Long;
+use POSIX qw(strftime);
+
+(my $ME = $0) =~ s|.*/||;
+
+# use File::Coda; # http://meyering.net/code/Coda/
+END {
+  defined fileno STDOUT or return;
+  close STDOUT and return;
+  warn "$ME: failed to close standard output: $!\n";
+  $? ||= 1;
+}
+
+sub usage ($)
+{
+  my ($exit_code) = @_;
+  my $STREAM = ($exit_code == 0 ? *STDOUT : *STDERR);
+  if ($exit_code != 0)
+    {
+      print $STREAM "Try '$ME --help' for more information.\n";
+    }
+  else
+    {
+      print $STREAM <<EOF;
+Usage: $ME [OPTIONS] [ARGS]
+
+Convert git log output to ChangeLog format.  If present, any ARGS
+are passed to "git log".  To avoid ARGS being parsed as options to
+$ME, they may be preceded by '--'.
+
+OPTIONS:
+
+   --amend=FILE FILE maps from an SHA1 to perl code (i.e., s/old/new/) that
+                  makes a change to SHA1's commit log text or metadata.
+   --append-dot append a dot to the first line of each commit message if
+                  there is no other punctuation or blank at the end.
+   --no-cluster never cluster commit messages under the same date/author
+                  header; the default is to cluster adjacent commit messages
+                  if their headers are the same and neither commit message
+                  contains multiple paragraphs.
+   --srcdir=DIR the root of the source tree, from which the .git/
+                  directory can be derived.
+   --since=DATE convert only the logs since DATE;
+                  the default is to convert all log entries.
+   --format=FMT set format string for commit subject and body;
+                  see 'man git-log' for the list of format metacharacters;
+                  the default is '%s%n%b%n'
+   --strip-tab  remove one additional leading TAB from commit message lines.
+   --strip-cherry-pick  remove data inserted by "git cherry-pick";
+                  this includes the "cherry picked from commit ..." line,
+                  and the possible final "Conflicts:" paragraph.
+   --help       display this help and exit
+   --version    output version information and exit
+
+EXAMPLE:
+
+  $ME --since=2008-01-01 > ChangeLog
+  $ME -- -n 5 foo > last-5-commits-to-branch-foo
+
+SPECIAL SYNTAX:
+
+The following types of strings are interpreted specially when they appear
+at the beginning of a log message line.  They are not copied to the output.
+
+  Copyright-paperwork-exempt: Yes
+    Append the "(tiny change)" notation to the usual "date name email"
+    ChangeLog header to mark a change that does not require a copyright
+    assignment.
+  Co-authored-by: Joe User <user\@example.com>
+    List the specified name and email address on a second
+    ChangeLog header, denoting a co-author.
+  Signed-off-by: Joe User <user\@example.com>
+    These lines are simply elided.
+
+In a FILE specified via --amend, comment lines (starting with "#") are ignored.
+FILE must consist of <SHA,CODE+> pairs where SHA is a 40-byte SHA1 (alone on
+a line) referring to a commit in the current project, and CODE refers to one
+or more consecutive lines of Perl code.  Pairs must be separated by one or
+more blank line.
+
+Here is sample input for use with --amend=FILE, from coreutils:
+
+3a169f4c5d9159283548178668d2fae6fced3030
+# fix typo in title:
+s/all tile types/all file types/
+
+1379ed974f1fa39b12e2ffab18b3f7a607082202
+# Due to a bug in vc-dwim, I mis-attributed a patch by Paul to myself.
+# Change the author to be Paul.  Note the escaped "@":
+s,Jim .*>,Paul Eggert <eggert\\\@cs.ucla.edu>,
+
+EOF
+    }
+  exit $exit_code;
+}
+
+# If the string $S is a well-behaved file name, simply return it.
+# If it contains white space, quotes, etc., quote it, and return the new string.
+sub shell_quote($)
+{
+  my ($s) = @_;
+  if ($s =~ m![^\w+/.,-]!)
+    {
+      # Convert each single quote to '\''
+      $s =~ s/\'/\'\\\'\'/g;
+      # Then single quote the string.
+      $s = "'$s'";
+    }
+  return $s;
+}
+
+sub quoted_cmd(@)
+{
+  return join (' ', map {shell_quote $_} @_);
+}
+
+# Parse file F.
+# Comment lines (starting with "#") are ignored.
+# F must consist of <SHA,CODE+> pairs where SHA is a 40-byte SHA1
+# (alone on a line) referring to a commit in the current project, and
+# CODE refers to one or more consecutive lines of Perl code.
+# Pairs must be separated by one or more blank line.
+sub parse_amend_file($)
+{
+  my ($f) = @_;
+
+  open F, '<', $f
+    or die "$ME: $f: failed to open for reading: $!\n";
+
+  my $fail;
+  my $h = {};
+  my $in_code = 0;
+  my $sha;
+  while (defined (my $line = <F>))
+    {
+      $line =~ /^\#/
+        and next;
+      chomp $line;
+      $line eq ''
+        and $in_code = 0, next;
+
+      if (!$in_code)
+        {
+          $line =~ /^([0-9a-fA-F]{40})$/
+            or (warn "$ME: $f:$.: invalid line; expected an SHA1\n"),
+              $fail = 1, next;
+          $sha = lc $1;
+          $in_code = 1;
+          exists $h->{$sha}
+            and (warn "$ME: $f:$.: duplicate SHA1\n"),
+              $fail = 1, next;
+        }
+      else
+        {
+          $h->{$sha} ||= '';
+          $h->{$sha} .= "$line\n";
+        }
+    }
+  close F;
+
+  $fail
+    and exit 1;
+
+  return $h;
+}
+
+# git_dir_option $SRCDIR
+#
+# From $SRCDIR, the --git-dir option to pass to git (none if $SRCDIR
+# is undef).  Return as a list (0 or 1 element).
+sub git_dir_option($)
+{
+  my ($srcdir) = @_;
+  my @res = ();
+  if (defined $srcdir)
+    {
+      my $qdir = shell_quote $srcdir;
+      my $cmd = "cd $qdir && git rev-parse --show-toplevel";
+      my $qcmd = shell_quote $cmd;
+      my $git_dir = qx($cmd);
+      defined $git_dir
+        or die "$ME: cannot run $qcmd: $!\n";
+      $? == 0
+        or die "$ME: $qcmd had unexpected exit code or signal ($?)\n";
+      chomp $git_dir;
+      push @res, "--git-dir=$git_dir/.git";
+    }
+  @res;
+}
+
+{
+  my $since_date;
+  my $format_string = '%s%n%b%n';
+  my $amend_file;
+  my $append_dot = 0;
+  my $cluster = 1;
+  my $strip_tab = 0;
+  my $strip_cherry_pick = 0;
+  my $srcdir;
+  GetOptions
+    (
+     help => sub { usage 0 },
+     version => sub { print "$ME version $VERSION\n"; exit },
+     'since=s' => \$since_date,
+     'format=s' => \$format_string,
+     'amend=s' => \$amend_file,
+     'append-dot' => \$append_dot,
+     'cluster!' => \$cluster,
+     'strip-tab' => \$strip_tab,
+     'strip-cherry-pick' => \$strip_cherry_pick,
+     'srcdir=s' => \$srcdir,
+    ) or usage 1;
+
+  defined $since_date
+    and unshift @ARGV, "--since=$since_date";
+
+  # This is a hash that maps an SHA1 to perl code (i.e., s/old/new/)
+  # that makes a correction in the log or attribution of that commit.
+  my $amend_code = defined $amend_file ? parse_amend_file $amend_file : {};
+
+  my @cmd = ('git',
+             git_dir_option $srcdir,
+             qw(log --log-size),
+             '--pretty=format:%H:%ct  %an  <%ae>%n%n'.$format_string, @ARGV);
+  open PIPE, '-|', @cmd
+    or die ("$ME: failed to run '". quoted_cmd (@cmd) ."': $!\n"
+            . "(Is your Git too old?  Version 1.5.1 or later is required.)\n");
+
+  my $prev_multi_paragraph;
+  my $prev_date_line = '';
+  my @prev_coauthors = ();
+  while (1)
+    {
+      defined (my $in = <PIPE>)
+        or last;
+      $in =~ /^log size (\d+)$/
+        or die "$ME:$.: Invalid line (expected log size):\n$in";
+      my $log_nbytes = $1;
+
+      my $log;
+      my $n_read = read PIPE, $log, $log_nbytes;
+      $n_read == $log_nbytes
+        or die "$ME:$.: unexpected EOF\n";
+
+      # Extract leading hash.
+      my ($sha, $rest) = split ':', $log, 2;
+      defined $sha
+        or die "$ME:$.: malformed log entry\n";
+      $sha =~ /^[0-9a-fA-F]{40}$/
+        or die "$ME:$.: invalid SHA1: $sha\n";
+
+      # If this commit's log requires any transformation, do it now.
+      my $code = $amend_code->{$sha};
+      if (defined $code)
+        {
+          eval 'use Safe';
+          my $s = new Safe;
+          # Put the unpreprocessed entry into "$_".
+          $_ = $rest;
+
+          # Let $code operate on it, safely.
+          my $r = $s->reval("$code")
+            or die "$ME:$.:$sha: failed to eval \"$code\":\n$@\n";
+
+          # Note that we've used this entry.
+          delete $amend_code->{$sha};
+
+          # Update $rest upon success.
+          $rest = $_;
+        }
+
+      # Remove lines inserted by "git cherry-pick".
+      if ($strip_cherry_pick)
+        {
+          $rest =~ s/^\s*Conflicts:\n.*//sm;
+          $rest =~ s/^\s*\(cherry picked from commit [\da-f]+\)\n//m;
+        }
+
+      my @line = split "\n", $rest;
+      my $author_line = shift @line;
+      defined $author_line
+        or die "$ME:$.: unexpected EOF\n";
+      $author_line =~ /^(\d+)  (.*>)$/
+        or die "$ME:$.: Invalid line "
+          . "(expected date/author/email):\n$author_line\n";
+
+      # Format 'Copyright-paperwork-exempt: Yes' as a standard ChangeLog
+      # `(tiny change)' annotation.
+      my $tiny = (grep (/^Copyright-paperwork-exempt:\s+[Yy]es$/, @line)
+                  ? '  (tiny change)' : '');
+
+      my $date_line = sprintf "%s  %s$tiny\n",
+        strftime ("%F", localtime ($1)), $2;
+
+      my @coauthors = grep /^Co-authored-by:.*$/, @line;
+      # Omit meta-data lines we've already interpreted.
+      @line = grep !/^(?:Signed-off-by:[ ].*>$
+                       |Co-authored-by:[ ]
+                       |Copyright-paperwork-exempt:[ ]
+                       )/x, @line;
+
+      # Remove leading and trailing blank lines.
+      if (@line)
+        {
+          while ($line[0] =~ /^\s*$/) { shift @line; }
+          while ($line[$#line] =~ /^\s*$/) { pop @line; }
+        }
+
+      # Record whether there are two or more paragraphs.
+      my $multi_paragraph = grep /^\s*$/, @line;
+
+      # Format 'Co-authored-by: A U Thor <email@example.com>' lines in
+      # standard multi-author ChangeLog format.
+      for (@coauthors)
+        {
+          s/^Co-authored-by:\s*/\t    /;
+          s/\s*</  </;
+
+          /<.*?@.*\..*>/
+            or warn "$ME: warning: missing email address for "
+              . substr ($_, 5) . "\n";
+        }
+
+      # If clustering of commit messages has been disabled, if this header
+      # would be different from the previous date/name/email/coauthors header,
+      # or if this or the previous entry consists of two or more paragraphs,
+      # then print the header.
+      if ( ! $cluster
+          || $date_line ne $prev_date_line
+          || "@coauthors" ne "@prev_coauthors"
+          || $multi_paragraph
+          || $prev_multi_paragraph)
+        {
+          $prev_date_line eq ''
+            or print "\n";
+          print $date_line;
+          @coauthors
+            and print join ("\n", @coauthors), "\n";
+        }
+      $prev_date_line = $date_line;
+      @prev_coauthors = @coauthors;
+      $prev_multi_paragraph = $multi_paragraph;
+
+      # If there were any lines
+      if (@line == 0)
+        {
+          warn "$ME: warning: empty commit message:\n  $date_line\n";
+        }
+      else
+        {
+          if ($append_dot)
+            {
+              # If the first line of the message has enough room, then
+              if (length $line[0] < 72)
+                {
+                  # append a dot if there is no other punctuation or blank
+                  # at the end.
+                  $line[0] =~ /[[:punct:]\s]$/
+                    or $line[0] .= '.';
+                }
+            }
+
+          # Remove one additional leading TAB from each line.
+          $strip_tab
+            and map { s/^\t// } @line;
+
+          # Prefix each non-empty line with a TAB.
+          @line = map { length $_ ? "\t$_" : '' } @line;
+
+          print "\n", join ("\n", @line), "\n";
+        }
+
+      defined ($in = <PIPE>)
+        or last;
+      $in ne "\n"
+        and die "$ME:$.: unexpected line:\n$in";
+    }
+
+  close PIPE
+    or die "$ME: error closing pipe from " . quoted_cmd (@cmd) . "\n";
+  # FIXME-someday: include $PROCESS_STATUS in the diagnostic
+
+  # Complain about any unused entry in the --amend=F specified file.
+  my $fail = 0;
+  foreach my $sha (keys %$amend_code)
+    {
+      warn "$ME:$amend_file: unused entry: $sha\n";
+      $fail = 1;
+    }
+
+  exit $fail;
+}
+
+# Local Variables:
+# mode: perl
+# indent-tabs-mode: nil
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "my $VERSION = '"
+# time-stamp-format: "%:y-%02m-%02d %02H:%02M"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "'; # UTC"
+# End:
diff --git a/conf/Makefile.common b/conf/Makefile.common
index 51fbaf99d..96e58c9a4 100644
--- a/conf/Makefile.common
+++ b/conf/Makefile.common
@@ -7,12 +7,7 @@ unexport LC_ALL
 
 # Platform specific options
 if COND_sparc64_ieee1275
-  CFLAGS_PLATFORM += -mno-app-regs
-  LDFLAGS_PLATFORM = -Wl,-melf64_sparc -mno-relax
-endif
-if COND_sparc64_emu
-  CFLAGS_PLATFORM += -mno-app-regs
-  LDFLAGS_PLATFORM = -Wl,--no-relax
+  LDFLAGS_PLATFORM = -Wl,-melf64_sparc
 endif
 if COND_arm
 if !COND_emu
@@ -39,21 +34,19 @@ CPPFLAGS_DEFAULT += -I$(top_srcdir)/grub-core/lib/libgcrypt-grub/src/
 CCASFLAGS_DEFAULT = $(CPPFLAGS_DEFAULT) -DASM_FILE=1
 BUILD_CPPFLAGS += $(CPPFLAGS_DEFAULT)
 
-LDADD_KERNEL = $(TARGET_LIBGCC)
-
-CFLAGS_KERNEL = $(CFLAGS_CPU) $(CFLAGS_PLATFORM) -ffreestanding
-LDFLAGS_KERNEL = $(LDFLAGS_CPU) $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) $(TARGET_LDFLAGS_STATIC_LIBGCC)
+CFLAGS_KERNEL = $(CFLAGS_PLATFORM) -ffreestanding
+LDFLAGS_KERNEL = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC)
 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 .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version -R .MIPS.abiflags
 
-CFLAGS_MODULE = $(CFLAGS_CPU) $(CFLAGS_PLATFORM) -ffreestanding
-LDFLAGS_MODULE = $(LDFLAGS_CPU) $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-r,-d
+CFLAGS_MODULE = $(CFLAGS_PLATFORM) -ffreestanding
+LDFLAGS_MODULE = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-r,-d
 CPPFLAGS_MODULE = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM)
 CCASFLAGS_MODULE = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM)
 
-CFLAGS_IMAGE = $(CFLAGS_CPU) $(CFLAGS_PLATFORM) -fno-builtin
-LDFLAGS_IMAGE = $(LDFLAGS_CPU) $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-S
+CFLAGS_IMAGE = $(CFLAGS_PLATFORM) -fno-builtin
+LDFLAGS_IMAGE = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-S
 CPPFLAGS_IMAGE = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM)
 CCASFLAGS_IMAGE = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM)
 
diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist
index 51f08c1f9..db6cfd12e 100644
--- a/conf/Makefile.extra-dist
+++ b/conf/Makefile.extra-dist
@@ -110,3 +110,26 @@ EXTRA_DIST += tests/dfly-mbr-mbexample.mbr.img.gz
 EXTRA_DIST += tests/dfly-mbr-mbexample.dfly.img.gz
 
 EXTRA_DIST += coreboot.cfg
+
+EXTRA_DIST += tests/file_filter/file
+EXTRA_DIST += tests/file_filter/file.gz
+EXTRA_DIST += tests/file_filter/file.gz.sig
+EXTRA_DIST += tests/file_filter/file.lzop
+EXTRA_DIST += tests/file_filter/file.lzop.sig
+EXTRA_DIST += tests/file_filter/file.xz
+EXTRA_DIST += tests/file_filter/file.xz.sig
+EXTRA_DIST += tests/file_filter/keys
+EXTRA_DIST += tests/file_filter/keys.pub
+EXTRA_DIST += tests/file_filter/test.cfg
+EXTRA_DIST += tests/syslinux/ubuntu10.04/isolinux/prompt.cfg
+EXTRA_DIST += tests/syslinux/ubuntu10.04/isolinux/gfxboot.cfg
+EXTRA_DIST += tests/syslinux/ubuntu10.04/isolinux/adtxt.cfg
+EXTRA_DIST += tests/syslinux/ubuntu10.04/isolinux/isolinux.cfg
+EXTRA_DIST += tests/syslinux/ubuntu10.04/isolinux/exithelp.cfg
+EXTRA_DIST += tests/syslinux/ubuntu10.04/isolinux/txt.cfg
+EXTRA_DIST += tests/syslinux/ubuntu10.04/isolinux/menu.cfg
+EXTRA_DIST += tests/syslinux/ubuntu10.04/isolinux/stdmenu.cfg
+EXTRA_DIST += tests/syslinux/ubuntu10.04/isolinux/dtmenu.cfg
+EXTRA_DIST += tests/syslinux/ubuntu10.04/isolinux/po4a.cfg
+EXTRA_DIST += tests/syslinux/ubuntu10.04/isolinux/rqtxt.cfg
+EXTRA_DIST += tests/syslinux/ubuntu10.04_grub.cfg.in
diff --git a/config.h.in b/config.h.in
index 4b6301441..9e8f9911b 100644
--- a/config.h.in
+++ b/config.h.in
@@ -7,11 +7,20 @@
 #endif
 
 #define GCRYPT_NO_DEPRECATED 1
+#define HAVE_MEMMOVE 1
 
 /* Define to 1 to enable disk cache statistics.  */
 #define DISK_CACHE_STATS @DISK_CACHE_STATS@
 #define BOOT_TIME_STATS @BOOT_TIME_STATS@
 
+/* We don't need those.  */
+#define MINILZO_CFG_SKIP_LZO_PTR 1
+#define MINILZO_CFG_SKIP_LZO_UTIL 1
+#define MINILZO_CFG_SKIP_LZO_STRING 1
+#define MINILZO_CFG_SKIP_LZO_INIT 1
+#define MINILZO_CFG_SKIP_LZO1X_1_COMPRESS 1
+#define MINILZO_CFG_SKIP_LZO1X_DECOMPRESS 1
+
 #if defined (GRUB_BUILD)
 #undef ENABLE_NLS
 #define BUILD_SIZEOF_LONG @BUILD_SIZEOF_LONG@
@@ -31,10 +40,6 @@
 #define HAVE_FONT_SOURCE @HAVE_FONT_SOURCE@
 /* Define if C symbols get an underscore after compilation. */
 #define HAVE_ASM_USCORE @HAVE_ASM_USCORE@
-/* Define it to \"addr32\" or \"addr32;\" to make GAS happy.  */
-#define ADDR32 @ADDR32@
-/* Define it to \"data32\" or \"data32;\" to make GAS happy. */
-#define DATA32 @DATA32@
 /* Define it to one of __bss_start, edata and _edata.  */
 #define BSS_START_SYMBOL @BSS_START_SYMBOL@
 /* Define it to either end or _end.  */
diff --git a/configure.ac b/configure.ac
index 31d2b0baf..891c14ff3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -78,12 +78,9 @@ fi
 
 # Default HOST_CPPFLAGS
 HOST_CPPFLAGS="$HOST_CPPFLAGS -Wall -W"
-HOST_CPPFLAGS="$HOST_CPPFLAGS -I\$(top_builddir)/include"
 HOST_CPPFLAGS="$HOST_CPPFLAGS -DGRUB_UTIL=1"
 
 TARGET_CPPFLAGS="$TARGET_CPPFLAGS -Wall -W"
-TARGET_CPPFLAGS="$TARGET_CPPFLAGS -I\$(top_srcdir)/include"
-TARGET_CPPFLAGS="$TARGET_CPPFLAGS -I\$(top_builddir)/include"
 
 case "$target_cpu" in
   i[[3456]]86)	target_cpu=i386 ;;
@@ -354,6 +351,9 @@ if test x"$target_cpu-$platform" = xsparc64-emu ; then
   HOST_CFLAGS="$HOST_CFLAGS -m64"
 fi
 
+CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=64"
+HOST_CPPFLAGS="$HOST_CPPFLAGS -D_FILE_OFFSET_BITS=64"
+
 AC_C_BIGENDIAN
 AC_CHECK_SIZEOF(void *)
 AC_CHECK_SIZEOF(long)
@@ -366,6 +366,14 @@ case "$host_os" in
    ;;
 esac
 
+case "$host_os" in
+  cygwin | windows* | mingw32* | aros*)
+     ;;
+  *)
+     AC_CHECK_SIZEOF(off_t)
+     test x"$ac_cv_sizeof_off_t" = x8 || AC_MSG_ERROR([Large file support is required]);;
+esac
+
 if test x$USE_NLS = xno; then
   HOST_CFLAGS="$HOST_CFLAGS -fno-builtin-gettext"
 fi
@@ -541,7 +549,7 @@ int main (void);
 
 TARGET_CFLAGS="$TARGET_CFLAGS $grub_cv_target_cc_w_extra_flags"
 
-AC_CACHE_CHECK([if compiling with clang], [grub_cv_cc_target_clang]
+AC_CACHE_CHECK([if compiling with clang], [grub_cv_cc_target_clang],
 [
 CFLAGS="$TARGET_CFLAGS"
 AC_COMPILE_IFELSE(
@@ -552,35 +560,42 @@ AC_COMPILE_IFELSE(
 ]])],
 [grub_cv_cc_target_clang=no], [grub_cv_cc_target_clang=yes])])
 
-# on x86 clang doesn't support .code16
-# on arm clang doesn't support .arch directive
-# on mips clang doesn't support privilegied instructions, doubleword store/load
-# and crashes with hand-written assembly
-if test "x$grub_cv_cc_target_clang" = xyes && ( test "x$target_cpu" = xi386 \
-   || test "x$target_cpu" = xx86_64 || test "x$target_cpu" = xarm \
-   || test "x$target_cpu" = xmips || test "x$target_cpu" = xmipsel ); then
-   TARGET_CCASFLAGS="$TARGET_CCASFLAGS -no-integrated-as"
+AC_CACHE_CHECK([for options to compile assembly], [grub_cv_cc_target_asm_compile], [
+test_program=
+case "x$target_cpu-$platform" in
+     xmips-* | xmipsel-*)
+        test_program=mips
+	;;
+     xi386-pc)
+       test_program=i386-pc
+	;;
+     xi386-* | xx86_64-*)
+       test_program=i386
+	;;
+     xpowerpc-* | xsparc64-* | xarm-*)
+        test_program=$target_cpu
+	;;
+esac
+if test x"$test_program" = x ; then
+  grub_cv_cc_target_asm_compile=
+else
+  found=no
+  for arg in "" "-no-integrated-as"; do
+    cmdline="$TARGET_CC -c -o /dev/null $TARGET_CCASFLAGS $arg $TARGET_CPPFLAGS $srcdir/asm-tests/$test_program.S"
+    echo "Running $cmdline" >&AS_MESSAGE_LOG_FD
+    if $cmdline >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then
+      grub_cv_cc_target_asm_compile="$arg"
+      found=yes
+      break
+    fi
+  done
+  if test x"$found" = xno ; then
+    AC_MSG_ERROR([could not compile assembly])
+  fi
 fi
+])
 
-if test "x$grub_cv_cc_target_clang" = xyes && test "x$target_cpu" = xpowerpc; then
-AC_CACHE_CHECK([if clang can handle ame instruction], [grub_cv_cc_target_clang_ame]
-[
-CFLAGS="$TARGET_CFLAGS"
-AC_COMPILE_IFELSE(
-[AC_LANG_PROGRAM([], [[
-   unsigned int a = 0, b = 0;
-   asm volatile ("{ame|addme} %0,%1" : "=r" (a) : "r" (b));
-   if (a)
-     return 1;
-]])],
-[grub_cv_cc_target_clang_ame=yes], [grub_cv_cc_target_clang_ame=no])])
-   # clang <= 3.3 doesn't handle most of ppc assembly, not even inline assembly
-   # used by gcrypt
-   if test x$grub_cv_cc_target_clang_ame = xno ; then
-     TARGET_CCASFLAGS="$TARGET_CCASFLAGS -no-integrated-as"
-     TARGET_CFLAGS="$TARGET_CFLAGS -no-integrated-as"
-   fi
-fi
+TARGET_CCASFLAGS="$TARGET_CCASFLAGS $grub_cv_cc_target_asm_compile"
 
 if test "x$target_cpu" = xi386 && test "x$platform" != xemu; then
   TARGET_CFLAGS="$TARGET_CFLAGS -march=i386"
@@ -663,6 +678,110 @@ if ( test "x$target_cpu" = xi386 || test "x$target_cpu" = xx86_64 ) && test "x$p
   TARGET_CFLAGS="$TARGET_CFLAGS -mno-mmx -mno-sse -mno-sse2 -mno-3dnow"
 fi
 
+# GRUB doesn't use float or doubles at all. Yet some toolchains may decide
+# that floats are a good fit to run instead of what's written in the code.
+# Given that floating point unit is disabled (if present to begin with)
+# when GRUB is running which may result in various hard crashes.
+if test x"$platform" != xemu ; then
+  AC_CACHE_CHECK([for options to get soft-float], grub_cv_target_cc_soft_float, [
+    grub_cv_target_cc_soft_float=no
+    if test "x$target_cpu" = xarm64; then
+       CFLAGS="$TARGET_CFLAGS -march=armv8-a+nofp+nosimd -Werror"
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
+		         [grub_cv_target_cc_soft_float="-march=armv8-a+nofp+nosimd"], [])
+    fi
+    if test "x$target_cpu" = xia64; then
+       CFLAGS="$TARGET_CFLAGS -mno-inline-float-divide -mno-inline-sqrt -Werror"
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
+		         [grub_cv_target_cc_soft_float="-mno-inline-float-divide -mno-inline-sqrt"], [])
+    fi
+    for cand in "-msoft-float -Xclang -msoft-float -Xclang -no-implicit-float" \
+		"-Xclang -msoft-float -Xclang -no-implicit-float" \
+		"-Xclang -msoft-float" "-msoft-float"; do
+      if test x"$grub_cv_target_cc_soft_float" != xno ; then
+        break
+      fi
+      CFLAGS="$TARGET_CFLAGS $cand -Werror"
+      AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
+		        [grub_cv_target_cc_soft_float="$cand"], [])
+    done
+  ])
+
+  if test x"$grub_cv_target_cc_soft_float" = xno ; then
+    AC_MSG_ERROR([could not force soft-float])
+  fi
+
+  case x"$grub_cv_target_cc_soft_float" in
+    x*"-Xclang"*)
+      # A trick so that clang doesn't see it on link stаge
+      TARGET_CPPFLAGS="$TARGET_CPPFLAGS $grub_cv_target_cc_soft_float"
+      ;;
+    *)
+      TARGET_CFLAGS="$TARGET_CFLAGS $grub_cv_target_cc_soft_float"
+      ;;
+  esac
+  case x"$grub_cv_target_cc_soft_float" in
+    x"-march=armv8-a+nofp+nosimd")
+      # +nosimd disables also the cache opcodes that we need in asm.
+      TARGET_CCASFLAGS="$TARGET_CCASFLAGS -march=armv8-a+nofp"
+      ;;
+    *)
+      TARGET_CCASFLAGS="$TARGET_CCASFLAGS $grub_cv_target_cc_soft_float"
+      ;;
+  esac
+
+fi
+
+if test x"$target_cpu" = xsparc64 ; then
+  AC_CACHE_CHECK([for options to reserve application registers], grub_cv_target_cc_mno_app_regs, [
+    grub_cv_target_cc_mno_app_regs=no
+    for cand in "-mllvm -sparc-reserve-app-registers" \
+		"-mno-app-regs"; do
+      if test x"$grub_cv_target_cc_mno_app_regs" != xno ; then
+        break
+      fi
+      CFLAGS="$TARGET_CFLAGS $cand -Werror"
+      CPPFLAGS="$TARGET_CPPFLAGS"
+      AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
+		        [grub_cv_target_cc_mno_app_regs="$cand"], [])
+    done
+  ])
+
+  if test x"$grub_cv_target_cc_mno_app_regs" = xno ; then
+    AC_MSG_ERROR([could not reserve application registers])
+  fi
+  if test x"$grub_cv_target_cc_mno_app_regs" = x"-mllvm -sparc-reserve-app-registers" ; then
+    # A trick so that clang doesn't see it on link stаge
+    TARGET_CPPFLAGS="$TARGET_CPPFLAGS $grub_cv_target_cc_mno_app_regs"
+  else
+    TARGET_CFLAGS="$TARGET_CFLAGS $grub_cv_target_cc_mno_app_regs"
+  fi
+
+  AC_CACHE_CHECK([for no-relax options], grub_cv_target_cc_mno_relax, [
+    grub_cv_target_cc_mno_relax=no
+    for cand in "-mno-relax" "-Wl,--no-relax"; do
+      if test x"$grub_cv_target_cc_mno_relax" != xno ; then
+        break
+      fi
+      LDFLAGS="$TARGET_LDFLAGS $cand -nostdlib -static"
+      CFLAGS="$TARGET_CFLAGS -Werror"
+      AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+	    asm (".globl start; start:");
+	    void __main (void);
+	    void __main (void) {}
+	    int main (void);
+	    ]], [[]])], [grub_cv_target_cc_mno_relax="$cand"], [])
+    done
+  ])
+  LDFLAGS="$TARGET_LDFLAGS"
+  CFLAGS="$TARGET_CFLAGS"
+
+  if test x"$grub_cv_target_cc_mno_relax" = xno ; then
+    AC_MSG_ERROR([could not find no-relax options])
+  fi
+  TARGET_LDFLAGS="$TARGET_LDFLAGS $grub_cv_target_cc_mno_relax"
+fi
+
 # By default, GCC 4.4 generates .eh_frame sections containing unwind
 # information in some cases where it previously did not. GRUB doesn't need
 # these and they just use up vital space. Restore the old compiler
@@ -864,7 +983,7 @@ AC_SUBST(TARGET_LDFLAGS_OLDMAGIC)
 
 LDFLAGS="$TARGET_LDFLAGS"
 
-if test "$target_cpu" = x86_64 || test "$target_cpu-$platform" = sparc64-emu ; then
+if test "$target_cpu" = x86_64 || test "$target_cpu" = sparc64 ; then
   # Use large model to support 4G memory
   AC_CACHE_CHECK([whether option -mcmodel=large works], grub_cv_cc_mcmodel, [
     CFLAGS="$TARGET_CFLAGS -mcmodel=large"
@@ -874,7 +993,7 @@ if test "$target_cpu" = x86_64 || test "$target_cpu-$platform" = sparc64-emu ; t
   ])
   if test "x$grub_cv_cc_mcmodel" = xyes; then
     TARGET_CFLAGS="$TARGET_CFLAGS -mcmodel=large"
-  elif test "$target_cpu-$platform" = sparc64-emu; then
+  elif test "$target_cpu" = sparc64; then
     TARGET_CFLAGS="$TARGET_CFLAGS -mcmodel=medany"
   fi
 fi
@@ -912,20 +1031,9 @@ if test "x$target_cpu" = xarm; then
   ])
   if test "x$grub_cv_cc_mthumb_interwork" = xyes; then
     TARGET_CFLAGS="$TARGET_CFLAGS -mthumb-interwork"
+  # Clang defaults to thumb interworking
   elif test "x$grub_cv_cc_target_clang" = xno ; then
     AC_MSG_ERROR([your compiler doesn't support -mthumb-interwork])
-  else
-    CFLAGS="$TARGET_CFLAGS"
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
-#if defined (__thumb__) && !defined (__thumb2__)
-#error thumb without interworking
-#endif
-]])],
-		      [no_interwork_ok=yes],
-		      [no_interwork_ok=no])
-    if test x$no_interwork_ok = xno ; then
-       AC_MSG_ERROR([attempt to compile to thumb with no thumb interwork])
-    fi
   fi
 fi
 
@@ -1023,22 +1131,17 @@ fi
 
 # Set them to their new values for the tests below.
 CC="$TARGET_CC"
-if test "x$TARGET_APPLE_LINKER" = x1 ; then
+if test x"$platform" = xemu ; then
+CFLAGS="$TARGET_CFLAGS -Wno-error"
+elif test "x$TARGET_APPLE_LINKER" = x1 ; then
 CFLAGS="$TARGET_CFLAGS -nostdlib -static -Wno-error"
 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
-TARGET_LIBGCC=
-else
-TARGET_LIBGCC=-lgcc
-fi
-
-LIBS="$TARGET_LIBGCC"
 
 grub_ASM_USCORE
-if test "x$TARGET_APPLE_LINKER" = x0 ; then
+if test "x$TARGET_APPLE_LINKER" = x0 && test x"$platform" != xemu; then
 if test x$grub_cv_asm_uscore = xyes; then
 DEFSYM="-Wl,--defsym,_abort=_main -Wl,--defsym,__main=_main"
 else
@@ -1048,7 +1151,9 @@ CFLAGS="$TARGET_CFLAGS -nostdlib $DEFSYM"
 fi
 
 # Check for libgcc symbols
-AC_CHECK_FUNCS(__bswapsi2 __bswapdi2 __ashldi3 __ashrdi3 __lshrdi3 __ucmpdi2 _restgpr_14_x)
+if test x"$platform" = xemu; then
+AC_CHECK_FUNCS(__udivsi3 __umodsi3 __divsi3 __modsi3 __divdi3 __moddi3 __udivdi3 __umoddi3 __ctzdi2 __ctzsi2 __aeabi_uidiv __aeabi_uidivmod __aeabi_idiv __aeabi_idivmod __aeabi_ulcmp __muldi3 __aeabi_lmul __aeabi_memcpy __aeabi_memset __aeabi_lasr __aeabi_llsl __aeabi_llsr _restgpr_14_x __ucmpdi2 __ashldi3 __ashrdi3 __lshrdi3 __bswapsi2 __bswapdi2 __bzero __register_frame_info __deregister_frame_info ___chkstk_ms __chkstk_ms)
+fi
 
 if test "x$TARGET_APPLE_LINKER" = x1 ; then
 CFLAGS="$TARGET_CFLAGS -nostdlib -static"
@@ -1073,8 +1178,6 @@ if test "x$target_cpu" = xi386; then
     grub_CHECK_END_SYMBOL
   fi
   CFLAGS="$TARGET_CFLAGS"
-  grub_I386_ASM_PREFIX_REQUIREMENT
-  grub_I386_ASM_ADDR32
 fi
 
 grub_PROG_NM_WORKS
@@ -1152,10 +1255,6 @@ else
 fi
 AC_SUBST([BOOT_TIME_STATS])
 
-AC_ARG_ENABLE([grub-emu-usb],
-	      [AS_HELP_STRING([--enable-grub-emu-usb],
-                             [build and install the `grub-emu' debugging utility with USB support (default=guessed)])])
-
 AC_ARG_ENABLE([grub-emu-sdl],
 	      [AS_HELP_STRING([--enable-grub-emu-sdl],
                              [build and install the `grub-emu' debugging utility with SDL support (default=guessed)])])
@@ -1166,34 +1265,6 @@ AC_ARG_ENABLE([grub-emu-pci],
 
 if test "$platform" = emu; then
 
-if test x"$enable_grub_emu_usb" != xyes ; then
-   grub_emu_usb_excuse="not enabled"
-fi
-
-if test x"$enable_grub_emu_pci" = xyes ; then
-   grub_emu_usb_excuse="conflicts with PCI support"
-fi
-
-[if [ x"$grub_emu_usb_excuse" = x ]; then
-    # Check for libusb libraries.]
-AC_CHECK_LIB([usb], [usb_claim_interface], [LIBUSB="-lusb"],
-    [grub_emu_usb_excuse=["need libusb library"]])
-    AC_SUBST([LIBUSB])
-[fi]
-[if [ x"$grub_emu_usb_excuse" = x ]; then
-    # Check for headers.]
-    AC_CHECK_HEADERS([usb.h], [],
-      [grub_emu_usb_excuse=["need libusb headers"]])
-[fi]
-if test x"$enable_grub_emu_usb" = xyes && test x"$grub_emu_usb_excuse" != x ; then
-  AC_MSG_ERROR([USB support for grub-emu was explicitly requested but can't be compiled ($grub_emu_usb_excuse)])
-fi
-if test x"$grub_emu_usb_excuse" = x ; then
-enable_grub_emu_usb=yes
-else
-enable_grub_emu_usb=no
-fi
-
 if test x"$enable_grub_emu_sdl" = xno ; then
   grub_emu_sdl_excuse="explicitly disabled"
 fi
@@ -1223,10 +1294,6 @@ if test x"$enable_grub_emu_pci" != xyes ; then
    grub_emu_pci_excuse="not enabled"
 fi
 
-if test x"$enable_grub_emu_usb" = xyes ; then
-   grub_emu_pci_excuse="conflicts with USB support"
-fi
-
 [if [ x"$grub_emu_pci_excuse" = x ]; then
       # Check for libpci libraries.]
    AC_CHECK_LIB([pciaccess], [pci_system_init], [LIBPCIACCESS="-lpciaccess"],
@@ -1235,7 +1302,7 @@ fi
 [fi]
 [if [ x"$grub_emu_pci_excuse" = x ]; then
     # Check for headers.]
-    AC_CHECK_HEADERS([pci/pci.h], [],
+    AC_CHECK_HEADERS([pciaccess.h], [],
       [grub_emu_pci_excuse=["need libpciaccess headers"]])
 [fi]
 
@@ -1247,14 +1314,12 @@ enable_grub_emu_pci=no
 fi
 
 AC_SUBST([enable_grub_emu_sdl])
-AC_SUBST([enable_grub_emu_usb])
 AC_SUBST([enable_grub_emu_pci])
 
 else
 
 # Ignore --enable-emu-* if platform is not emu
 enable_grub_emu_sdl=no
-enable_grub_emu_usb=no
 enable_grub_emu_pci=no
 fi
 
@@ -1463,7 +1528,7 @@ fi
 if test x"$grub_mount_excuse" = x ; then
   # Check for fuse headers.
   SAVED_CPPFLAGS="$CPPFLAGS"
-  CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26"
+  CPPFLAGS="$CPPFLAGS -DFUSE_USE_VERSION=26"
   AC_CHECK_HEADERS([fuse/fuse.h], [],
   	[grub_mount_excuse=["need FUSE headers"]])
   CPPFLAGS="$SAVED_CPPFLAGS"
@@ -1598,8 +1663,6 @@ AS_IF([test x$target_cpu = xi386 -a x$platform = xqemu],
 	    [AC_SUBST([GRUB_BOOT_MACHINE_LINK_ADDR], 0xffe00)])
 
 AC_SUBST(HAVE_ASM_USCORE)
-AC_SUBST(ADDR32)
-AC_SUBST(DATA32)
 AC_SUBST(BSS_START_SYMBOL)
 AC_SUBST(END_SYMBOL)
 AC_SUBST(PACKAGE)
@@ -1613,15 +1676,15 @@ if test x"$enable_werror" != xno ; then
   HOST_CFLAGS="$HOST_CFLAGS -Werror"
 fi
 
-if test "x$grub_cv_cc_target_clang" = xno; then
-   TARGET_LDFLAGS_STATIC_LIBGCC="-static-libgcc"
-else
-   TARGET_LDFLAGS_STATIC_LIBGCC=
-fi
-
 TARGET_CPP="$TARGET_CC -E"
 TARGET_CCAS=$TARGET_CC
 
+# Includes which include make-time substitutions. They must come last
+# as to avoid executing top_builddir in shell.
+HOST_CPPFLAGS="$HOST_CPPFLAGS -I\$(top_builddir)/include"
+TARGET_CPPFLAGS="$TARGET_CPPFLAGS -I\$(top_srcdir)/include"
+TARGET_CPPFLAGS="$TARGET_CPPFLAGS -I\$(top_builddir)/include"
+
 GRUB_TARGET_CPU="${target_cpu}"
 GRUB_PLATFORM="${platform}"
 
@@ -1629,8 +1692,6 @@ AC_SUBST(GRUB_TARGET_CPU)
 AC_SUBST(GRUB_PLATFORM)
 
 AC_SUBST(TARGET_OBJCONV)
-AC_SUBST(TARGET_LIBGCC)
-AC_SUBST(TARGET_LDFLAGS_STATIC_LIBGCC)
 AC_SUBST(TARGET_CPP)
 AC_SUBST(TARGET_CCAS)
 AC_SUBST(TARGET_OBJ2ELF)
@@ -1660,7 +1721,6 @@ AC_SUBST(BUILD_LIBM)
 
 AM_CONDITIONAL([COND_real_platform], [test x$platform != xnone])
 AM_CONDITIONAL([COND_emu], [test x$platform = xemu])
-AM_CONDITIONAL([COND_clang], [test x$grub_cv_cc_target_clang = xyes])
 AM_CONDITIONAL([COND_i386_pc], [test x$target_cpu = xi386 -a x$platform = xpc])
 AM_CONDITIONAL([COND_i386_efi], [test x$target_cpu = xi386 -a x$platform = xefi])
 AM_CONDITIONAL([COND_ia64_efi], [test x$target_cpu = xia64 -a x$platform = xefi])
@@ -1695,7 +1755,6 @@ AM_CONDITIONAL([COND_HOST_XNU], [test x$host_kernel = xxnu])
 AM_CONDITIONAL([COND_HOST_ILLUMOS], [test x$host_kernel = xillumos])
 
 AM_CONDITIONAL([COND_MAN_PAGES], [test x$cross_compiling = xno -a x$HELP2MAN != x])
-AM_CONDITIONAL([COND_GRUB_EMU_USB], [test x$enable_grub_emu_usb = xyes])
 AM_CONDITIONAL([COND_GRUB_EMU_SDL], [test x$enable_grub_emu_sdl = xyes])
 AM_CONDITIONAL([COND_GRUB_EMU_PCI], [test x$enable_grub_emu_pci = xyes])
 AM_CONDITIONAL([COND_GRUB_MKFONT], [test x$enable_grub_mkfont = xyes])
@@ -1773,11 +1832,6 @@ echo "*******************************************************"
 echo GRUB2 will be compiled with following components:
 echo Platform: "$target_cpu"-"$platform"
 if [ x"$platform" = xemu ]; then
-if [ x"$grub_emu_usb_excuse" = x ]; then
-echo USB support for grub-emu: Yes
-else
-echo USB support for grub-emu: No "($grub_emu_usb_excuse)"
-fi
 if [ x"$grub_emu_sdl_excuse" = x ]; then
 echo SDL support for grub-emu: Yes
 else
diff --git a/docs/grub.texi b/docs/grub.texi
index 46b9e7f8e..4af22aff8 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -5848,7 +5848,7 @@ Following variables must be defined:
 
 @multitable  @columnfractions .30 .65
 @item GRUB_PAYLOADS_DIR @tab directory containing the required kernels
-@item GRUB_CBFSTOOL @tab cbfstoll from Coreboot package (for coreboot platform only)
+@item GRUB_CBFSTOOL @tab cbfstool from Coreboot package (for coreboot platform only)
 @item GRUB_COREBOOT_ROM @tab empty Coreboot ROM
 @item GRUB_QEMU_OPTS @tab additional options to be supplied to QEMU
 @end multitable
diff --git a/gentpl.py b/gentpl.py
index bdcae1a1c..f177883f8 100644
--- a/gentpl.py
+++ b/gentpl.py
@@ -76,6 +76,12 @@ for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i)
 # Flattened Device Trees (FDT)
 GROUPS["fdt"] = [ "arm64_efi", "arm_uboot", "arm_efi" ]
 
+# Needs software helpers for division
+# Must match GRUB_DIVISION_IN_SOFTWARE in misc.h
+GROUPS["softdiv"] = GROUPS["arm"] + ["ia64_efi"]
+GROUPS["no_softdiv"]   = GRUB_PLATFORMS[:]
+for i in GROUPS["softdiv"]: GROUPS["no_softdiv"].remove(i)
+
 # Miscelaneous groups schedulded to disappear in future
 GROUPS["i386_coreboot_multiboot_qemu"] = ["i386_coreboot", "i386_multiboot", "i386_qemu"]
 GROUPS["nopc"] = GRUB_PLATFORMS[:]; GROUPS["nopc"].remove("i386_pc")
@@ -600,7 +606,7 @@ def foreach_enabled_platform(defn, closure):
 #    enable = emu;
 #    enable = i386;
 #    enable = mips_loongson;
-#    emu_condition = COND_GRUB_EMU_USB;
+#    emu_condition = COND_GRUB_EMU_SDL;
 #  };
 #
 def under_platform_specific_conditionals(defn, platform, closure):
@@ -753,7 +759,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 $< $@; \
 fi
 """)
 
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index 5c087c83b..af0c7f47c 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -76,6 +76,11 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i18n.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/kernel.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/list.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/misc.h
+if COND_emu
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/compiler-rt-emu.h
+else
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/compiler-rt.h
+endif
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/parser.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/partition.h
@@ -83,9 +88,6 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
 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
-KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h
-endif
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h
 
 if COND_i386_pc
@@ -248,9 +250,6 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
 if COND_GRUB_EMU_SDL
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sdl.h
 endif
-if COND_GRUB_EMU_USB
-KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libusb.h
-endif
 if COND_GRUB_EMU_PCI
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libpciaccess.h
 endif
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index a084b4110..c9b306e20 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -83,8 +83,6 @@ kernel = {
   x86_64_xen_ldflags       = '$(TARGET_IMG_LDFLAGS)';
   x86_64_xen_ldflags       = '$(TARGET_IMG_BASE_LDOPT),0';
 
-  ldadd = '$(LDADD_KERNEL)';
-
   mips_loongson_ldflags    = '-Wl,-Ttext,0x80200000';
   powerpc_ieee1275_ldflags = '-Wl,-Ttext,0x200000';
   sparc64_ieee1275_ldflags = '-Wl,-Ttext,0x4400';
@@ -132,6 +130,7 @@ kernel = {
   common = kern/rescue_reader.c;
   common = kern/term.c;
 
+  noemu = kern/compiler-rt.c;
   noemu = kern/mm.c;
   noemu = kern/time.c;
   noemu = kern/generic/millisleep.c;
@@ -159,6 +158,8 @@ kernel = {
   terminfoinkernel = commands/extcmd.c;
   terminfoinkernel = lib/arg.c;
 
+  softdiv = lib/division.c;
+
   i386 = kern/i386/dl.c;
   i386_xen = kern/i386/dl.c;
 
@@ -252,6 +253,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;
@@ -263,7 +265,7 @@ kernel = {
   arm = kern/arm/cache_armv7.S;
   extra_dist = kern/arm/cache.S;
   arm = kern/arm/cache.c;
-  arm = kern/arm/misc.S;
+  arm = kern/arm/compiler-rt.S;
 
   arm64 = kern/arm64/cache.c;
   arm64 = kern/arm64/cache_flush.S;
@@ -441,13 +443,13 @@ image = {
   common = lib/xzembed/xz_dec_bcj.c;
   common = lib/xzembed/xz_dec_lzma2.c;
   common = lib/xzembed/xz_dec_stream.c;
+  common = kern/compiler-rt.c;
 
   cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed -DGRUB_EMBED_DECOMPRESSOR=1';
 
   objcopyflags = '-O binary';
-  mips_ldflags = '$(TARGET_LDFLAGS_STATIC_LIBGCC) -Wl,-Ttext,$(TARGET_DECOMPRESSOR_LINK_ADDR)';
-  ldadd = '$(TARGET_LIBGCC)';
-  cflags = '-Wno-unreachable-code $(TARGET_LDFLAGS_STATIC_LIBGCC)';
+  mips_ldflags = '-Wl,-Ttext,$(TARGET_DECOMPRESSOR_LINK_ADDR)';
+  cflags = '-Wno-unreachable-code';
   enable = mips;
 };
 
@@ -459,9 +461,7 @@ image = {
   cppflags = '-DGRUB_EMBED_DECOMPRESSOR=1';
 
   objcopyflags = '-O binary';
-  mips_ldflags = '$(TARGET_LDFLAGS_STATIC_LIBGCC) -Wl,-Ttext,$(TARGET_DECOMPRESSOR_LINK_ADDR)';
-  ldadd = '$(TARGET_LIBGCC)';
-  cflags = '$(TARGET_LDFLAGS_STATIC_LIBGCC)';
+  mips_ldflags = '-Wl,-Ttext,$(TARGET_DECOMPRESSOR_LINK_ADDR)';
   enable = mips;
 };
 
@@ -479,7 +479,7 @@ image = {
   name = fwstart;
   mips_loongson = boot/mips/loongson/fwstart.S;
   objcopyflags = '-O binary';
-  ldflags = '$(TARGET_LDFLAGS_STATIC_LIBGCC) $(TARGET_LIBGCC) -Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic';
+  ldflags = '-Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic';
   enable = mips_loongson;
 };
 
@@ -487,7 +487,7 @@ image = {
   name = fwstart_fuloong2f;
   mips_loongson = boot/mips/loongson/fuloong2f.S;
   objcopyflags = '-O binary';
-  ldflags = '$(TARGET_LDFLAGS_STATIC_LIBGCC) $(TARGET_LIBGCC) -Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic';
+  ldflags = '-Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic';
   enable = mips_loongson;
 };
 
@@ -509,13 +509,6 @@ module = {
   enable = x86;
 };
 
-module = {
-  name = libusb;
-  emu = bus/usb/emu/usb.c;
-  enable = emu;
-  condition = COND_GRUB_EMU_USB;
-};
-
 module = {
   name = lsspd;
   mips_loongson = commands/mips/loongson/lsspd.c;
@@ -530,13 +523,6 @@ module = {
   enable = usb;
 };
 
-module = {
-  name = emuusb;
-  common = bus/usb/usb.c;
-  enable = emu;
-  condition = COND_GRUB_EMU_USB;
-};
-
 module = {
   name = usbserial_common;
   common = bus/usb/serial/common.c;
@@ -2009,11 +1995,42 @@ module = {
   enable = xen;
 };
 
+module = {
+  name = div;
+  common = lib/division.c;
+  enable = no_softdiv;
+};
+
 module = {
   name = div_test;
   common = tests/div_test.c;
 };
 
+module = {
+  name = mul_test;
+  common = tests/mul_test.c;
+};
+
+module = {
+  name = shift_test;
+  common = tests/shift_test.c;
+};
+
+module = {
+  name = cmp_test;
+  common = tests/cmp_test.c;
+};
+
+module = {
+  name = ctz_test;
+  common = tests/ctz_test.c;
+};
+
+module = {
+  name = bswap_test;
+  common = tests/bswap_test.c;
+};
+
 module = {
   name = videotest_checksum;
   common = tests/videotest_checksum.c;
diff --git a/grub-core/boot/decompressor/minilib.c b/grub-core/boot/decompressor/minilib.c
index 94edfd561..fc46ee07b 100644
--- a/grub-core/boot/decompressor/minilib.c
+++ b/grub-core/boot/decompressor/minilib.c
@@ -21,7 +21,7 @@
 #include <grub/decompressor.h>
 
 void *
-memset (void *s, int c, grub_size_t len)
+grub_memset (void *s, int c, grub_size_t len)
 {
   grub_uint8_t *ptr;
   for (ptr = s; len; ptr++, len--)
@@ -68,15 +68,6 @@ grub_memcmp (const void *s1, const void *s2, grub_size_t n)
   return 0;
 }
 
-int memcmp (const void *s1, const void *s2, grub_size_t n)
-  __attribute__ ((alias ("grub_memcmp")));
-
-void *memmove (void *dest, const void *src, grub_size_t n)
-  __attribute__ ((alias ("grub_memmove")));
-
-void *memcpy (void *dest, const void *src, grub_size_t n)
-  __attribute__ ((alias ("grub_memmove")));
-
 void *grub_decompressor_scratch;
 
 void
diff --git a/grub-core/boot/i386/pc/boot.S b/grub-core/boot/i386/pc/boot.S
index b4975e2d0..2bd0b2d28 100644
--- a/grub-core/boot/i386/pc/boot.S
+++ b/grub-core/boot/i386/pc/boot.S
@@ -165,8 +165,8 @@ start:
 	 * this area.
 	 */
 
-	. = _start + GRUB_BOOT_MACHINE_BPB_START
-	. = _start + 4
+	.org GRUB_BOOT_MACHINE_BPB_START
+	.org 4
 #endif
 #ifdef HYBRID_BOOT
 	floppy
@@ -174,23 +174,23 @@ start:
 	scratch
 #endif
 
-	. = _start + GRUB_BOOT_MACHINE_BPB_END
+	.org GRUB_BOOT_MACHINE_BPB_END
 	/*
 	 * End of BIOS parameter block.
 	 */
 
-kernel_address:
+LOCAL(kernel_address):
 	.word	GRUB_BOOT_MACHINE_KERNEL_ADDR
 
 #ifndef HYBRID_BOOT
-	. = _start + GRUB_BOOT_MACHINE_KERNEL_SECTOR
-kernel_sector:
+	.org GRUB_BOOT_MACHINE_KERNEL_SECTOR
+LOCAL(kernel_sector):
 	.long	1
-kernel_sector_high:
+LOCAL(kernel_sector_high):
 	.long	0
 #endif
 
-	. = _start + GRUB_BOOT_MACHINE_BOOT_DRIVE
+	.org GRUB_BOOT_MACHINE_BOOT_DRIVE
 boot_drive:
 	.byte 0xff	/* the disk to load kernel from */
 			/* 0xff means use the boot drive */
@@ -208,7 +208,7 @@ LOCAL(after_BPB):
          * possible boot drive. If GRUB is installed into a floppy,
          * this does nothing (only jump).
          */
-	. = _start + GRUB_BOOT_MACHINE_DRIVE_CHECK
+	.org GRUB_BOOT_MACHINE_DRIVE_CHECK
 boot_drive_check:
         jmp     3f	/* grub-setup may overwrite this jump */
         testb   $0x80, %dl
@@ -275,7 +275,7 @@ real_start:
 	andw	$1, %cx
 	jz	LOCAL(chs_mode)
 
-lba_mode:
+LOCAL(lba_mode):
 	xorw	%ax, %ax
 	movw	%ax, 4(%si)
 
@@ -290,9 +290,9 @@ lba_mode:
 	movw	$0x0010, (%si)
 
 	/* the absolute address */
-	movl	kernel_sector, %ebx
+	movl	LOCAL(kernel_sector), %ebx
 	movl	%ebx, 8(%si)
-	movl	kernel_sector_high, %ebx
+	movl	LOCAL(kernel_sector_high), %ebx
 	movl	%ebx, 12(%si)
 
 	/* the segment of buffer address */
@@ -361,13 +361,13 @@ LOCAL(final_init):
 
 setup_sectors:
 	/* load logical sector start (top half) */
-	movl	kernel_sector_high, %eax
+	movl	LOCAL(kernel_sector_high), %eax
 
 	orl	%eax, %eax
 	jnz	LOCAL(geometry_error)
 
 	/* load logical sector start (bottom half) */
-	movl	kernel_sector, %eax
+	movl	LOCAL(kernel_sector), %eax
 
 	/* zero %edx */
 	xorl	%edx, %edx
@@ -452,7 +452,7 @@ LOCAL(copy_buffer):
 	popa
 
 	/* boot kernel */
-	jmp	*(kernel_address)
+	jmp	*(LOCAL(kernel_address))
 
 /* END OF MAIN LOOP */
 
@@ -511,13 +511,13 @@ LOCAL(message):
 	 */
 
 #ifdef HYBRID_BOOT
-	. = _start + 0x1b0
-kernel_sector:
+	.org 0x1b0
+LOCAL(kernel_sector):
 	.long	1
-kernel_sector_high:
+LOCAL(kernel_sector_high):
 	.long	0
 #endif
-	. = _start + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC
+	.org GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC
 nt_magic:
 	.long 0
 	.word 0
@@ -528,7 +528,7 @@ nt_magic:
 	 *  sneaky, huh?
 	*/
 
-	. = _start + GRUB_BOOT_MACHINE_PART_START
+	.org GRUB_BOOT_MACHINE_PART_START
 
 #ifndef HYBRID_BOOT
 	floppy
@@ -536,7 +536,7 @@ nt_magic:
 	scratch
 #endif
 
-	. = _start + GRUB_BOOT_MACHINE_PART_END
+	.org GRUB_BOOT_MACHINE_PART_END
 	
 /* the last 2 bytes in the sector 0 contain the signature */
 	.word	GRUB_BOOT_MACHINE_SIGNATURE
diff --git a/grub-core/boot/i386/pc/cdboot.S b/grub-core/boot/i386/pc/cdboot.S
index 92df7c76f..de4f80929 100644
--- a/grub-core/boot/i386/pc/cdboot.S
+++ b/grub-core/boot/i386/pc/cdboot.S
@@ -43,7 +43,7 @@ _start:
 LOCAL(next):
 	jmp	1f
 
-	. = start + 8
+	.org 8
 
 bi_pvd:
 	.long 0		/* LBA of primary volume descriptor.  */
@@ -168,6 +168,6 @@ err_noboot_msg:
 err_cdfail_msg:
 	.ascii	"cdrom read fails\0"
 
-	. = start + 0x7FF
+	.org 0x7FF
 
 	.byte	0
diff --git a/grub-core/boot/i386/pc/diskboot.S b/grub-core/boot/i386/pc/diskboot.S
index d030a14c9..1ee4cf5b2 100644
--- a/grub-core/boot/i386/pc/diskboot.S
+++ b/grub-core/boot/i386/pc/diskboot.S
@@ -362,7 +362,7 @@ LOCAL(message):
 	.word 0
 	.word 0
 
-	. = _start + 0x200 - GRUB_BOOT_MACHINE_LIST_SIZE
+	.org 0x200 - GRUB_BOOT_MACHINE_LIST_SIZE
 LOCAL(firstlist):	/* this label has to be before the first list entry!!! */
         /* fill the first data listing with the default */
 blocklist_default_start:
diff --git a/grub-core/boot/i386/pc/lnxboot.S b/grub-core/boot/i386/pc/lnxboot.S
index 87e56a2fd..2dda0e06b 100644
--- a/grub-core/boot/i386/pc/lnxboot.S
+++ b/grub-core/boot/i386/pc/lnxboot.S
@@ -41,7 +41,7 @@ data_start:
 	xorl	%ebp, %ebp
 	jmp	LOCAL(linux_next)
 
-	. = data_start + 0x1F1
+	.org 0x1F1
 
 setup_sects:
 	.byte	CODE_SECTORS
@@ -292,4 +292,4 @@ LOCAL(fail):
 err_int15_msg:
 	.ascii	"move memory fails\0"
 
-	. = _start + CODE_SECTORS * 512
+	.org (CODE_SECTORS * 512 + 512)
diff --git a/grub-core/boot/i386/pc/pxeboot.S b/grub-core/boot/i386/pc/pxeboot.S
index 446bfc781..b695b24d0 100644
--- a/grub-core/boot/i386/pc/pxeboot.S
+++ b/grub-core/boot/i386/pc/pxeboot.S
@@ -38,5 +38,5 @@ start:
 	/* This region is a junk. Do you say that this is wasteful?
 	   But I like that the memory layout of the body is consistent
 	   among different kernels rather than scamping just for 1.5KB. */
-	. = _start + 0x8200 - 0x7C00 - 0x200 - 1
+	.org  0x8200 - 0x7C00 - 0x200 - 1
 	.byte	0
diff --git a/grub-core/boot/i386/pc/startup_raw.S b/grub-core/boot/i386/pc/startup_raw.S
index 279674030..8bce7985c 100644
--- a/grub-core/boot/i386/pc/startup_raw.S
+++ b/grub-core/boot/i386/pc/startup_raw.S
@@ -50,23 +50,23 @@ LOCAL (base):
 	 *  This is a special data area.
 	 */
 
-	. = _start + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE
+	.org GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE
 LOCAL(compressed_size):
 	.long 0
-	. = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE
+	.org GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE
 LOCAL(uncompressed_size):
 	.long 0
 
-	. = _start + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY
+	.org GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY
 reed_solomon_redundancy:
 	.long	0
-	. = _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH
+	.org GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH
 	.short	(LOCAL(reed_solomon_part) - _start)
 
 /*
  *  This is the area for all of the special variables.
  */
-	. = _start + GRUB_DECOMPRESSOR_I386_PC_BOOT_DEVICE
+	.org GRUB_DECOMPRESSOR_I386_PC_BOOT_DEVICE
 LOCAL(boot_dev):
 	.byte	0xFF, 0xFF, 0xFF
 LOCAL(boot_drive):
@@ -89,13 +89,13 @@ LOCAL (codestart):
 	sti		/* we're safe again */
 
 	/* save the boot drive */
-	ADDR32	movb	%dl, LOCAL(boot_drive)
+	movb	%dl, LOCAL(boot_drive)
 
 	/* reset disk system (%ah = 0) */
 	int	$0x13
 
 	/* transition to protected mode */
-	DATA32	call real_to_prot
+	calll	real_to_prot
 
 	/* The ".code32" directive takes GAS out of 16-bit mode. */
 	.code32
@@ -149,7 +149,7 @@ gate_a20_try_bios:
 	movw	$0x2401, %ax
 	int	$0x15
 
-	DATA32	call	real_to_prot
+	calll	real_to_prot
 	.code32
 
 	popl	%ebp
diff --git a/grub-core/boot/i386/qemu/boot.S b/grub-core/boot/i386/qemu/boot.S
index bdd68c704..8c3a1db71 100644
--- a/grub-core/boot/i386/qemu/boot.S
+++ b/grub-core/boot/i386/qemu/boot.S
@@ -31,7 +31,7 @@ _start:
 
 	jmp	1f
 
-	. = _start + GRUB_BOOT_I386_QEMU_CORE_ENTRY_ADDR
+	.org GRUB_BOOT_I386_QEMU_CORE_ENTRY_ADDR
 VARIABLE(grub_core_entry_addr)
 	.long	0
 1:
@@ -48,8 +48,9 @@ VARIABLE(grub_core_entry_addr)
 	/* Transition to protected mode.  We use pushl to force generation
 	   of a flat return address.  */
 	pushl	$1f
-	DATA32	jmp real_to_prot
+	jmp	real_to_prot
 	.code32
+1:
 	/* Ensure A20 is enabled. We're in qemu, so control port A works
 	   and there is no need to wait since there is no real logic, it's
 	   all emulated.  */
@@ -57,7 +58,6 @@ VARIABLE(grub_core_entry_addr)
 	andb	$(~0x03), %al
 	orb	$0x02, %al
 	outb	$0x92
-1:
 	movl	EXT_C(grub_core_entry_addr), %edx
 	jmp	*%edx
 
@@ -66,9 +66,9 @@ VARIABLE(grub_core_entry_addr)
 	/* Intel, in its infinite wisdom, decided to put the i8086 entry point
 	   *right here* and this is why we need this kludge.  */
 
-	. = GRUB_BOOT_MACHINE_SIZE - 16
+	.org GRUB_BOOT_MACHINE_SIZE - 16
 
        .code16
        
 	jmp	_start
-	. = GRUB_BOOT_MACHINE_SIZE
+	.org GRUB_BOOT_MACHINE_SIZE
diff --git a/grub-core/boot/mips/loongson/fwstart.S b/grub-core/boot/mips/loongson/fwstart.S
index 6ae326990..71bab6dc8 100644
--- a/grub-core/boot/mips/loongson/fwstart.S
+++ b/grub-core/boot/mips/loongson/fwstart.S
@@ -162,7 +162,7 @@ retry_cs5536:
 
 	b continue
 
-	. = start + GRUB_CPU_LOONGSON_FLASH_TLB_REFILL - GRUB_CPU_LOONGSON_FLASH_START
+	.org GRUB_CPU_LOONGSON_FLASH_TLB_REFILL - GRUB_CPU_LOONGSON_FLASH_START
 tlb_refill:	
 	mfc0 $s1, GRUB_CPU_LOONGSON_COP0_EPC
 	mfc0 $s2, GRUB_CPU_LOONGSON_COP0_BADVADDR
@@ -196,13 +196,13 @@ tlb_refill:
 	b fatal
 	 addiu $a0, $a0, %lo(unhandled_tlb_refill)
 
-	. = start + GRUB_CPU_LOONGSON_FLASH_CACHE_ERROR - GRUB_CPU_LOONGSON_FLASH_START
+	.org GRUB_CPU_LOONGSON_FLASH_CACHE_ERROR - GRUB_CPU_LOONGSON_FLASH_START
 cache_error:
 	lui $a0, %hi(unhandled_cache_error)
 	b fatal
 	 addiu $a0, $a0, %lo(unhandled_cache_error)
 
-	. = start + GRUB_CPU_LOONGSON_FLASH_OTHER_EXCEPTION - GRUB_CPU_LOONGSON_FLASH_START
+	.org GRUB_CPU_LOONGSON_FLASH_OTHER_EXCEPTION - GRUB_CPU_LOONGSON_FLASH_START
 other_exception:
 	mfc0 $s0, GRUB_CPU_LOONGSON_COP0_CAUSE
 	mfc0 $s1, GRUB_CPU_LOONGSON_COP0_EPC
diff --git a/grub-core/boot/mips/startup_raw.S b/grub-core/boot/mips/startup_raw.S
index 29e93c17e..fd95c3134 100644
--- a/grub-core/boot/mips/startup_raw.S
+++ b/grub-core/boot/mips/startup_raw.S
@@ -21,6 +21,7 @@
 #include <grub/offsets.h>
 #include <grub/machine/memory.h>
 #include <grub/machine/kernel.h>
+#include <grub/cpu/kernel.h>
 #include <grub/offsets.h>
 
 #define BASE_ADDR 8
@@ -32,6 +33,7 @@
 	.globl __start, _start, start
 	.set noreorder
 	.set nomacro
+	mips_attributes
 __start:
 _start:
 start:		
@@ -39,13 +41,13 @@ start:
 	bal codestart
 	 nop
 base:	
-	. = _start + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE
+	.org GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE
 compressed_size:
 	.long 0
-	. = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE
+	.org GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE
 uncompressed_size:
 	.long 0
-	. = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_ADDR
+	.org GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_ADDR
 uncompressed_addr:
 	.long 0
 codestart:
@@ -150,18 +152,18 @@ digcont:
 1:
 	jr $ra
 	 nop
-busclockstr:	.asciiz "busclock="
-cpuclockstr:	.asciiz "cpuclock="
-memsizestr:	.asciiz "memsize="
-highmemsizestr:	.asciiz "highmemsize="
-machtype_yeeloong_str1:	.asciiz "machtype=8.9"
-machtype_yeeloong_str2:	.asciiz "machtype=lemote-yeeloong-"
-machtype_fuloong2f_str:	.asciiz "machtype=lemote-fuloong-2f"
-machtype_fuloong2e_str:	.asciiz "machtype=lemote-fuloong-2e"
-pmon_yeeloong_str:	.asciiz "PMON_VER=LM8"
-pmon_fuloong2f_str:	.asciiz "PMON_VER=LM6"
-pmon_yeeloong_verstr:	.asciiz "Version=LM8"
-pmon_fuloong2f_verstr:	.asciiz "Version=LM6"
+busclockstr:	.asciz "busclock="
+cpuclockstr:	.asciz "cpuclock="
+memsizestr:	.asciz "memsize="
+highmemsizestr:	.asciz "highmemsize="
+machtype_yeeloong_str1:	.asciz "machtype=8.9"
+machtype_yeeloong_str2:	.asciz "machtype=lemote-yeeloong-"
+machtype_fuloong2f_str:	.asciz "machtype=lemote-fuloong-2f"
+machtype_fuloong2e_str:	.asciz "machtype=lemote-fuloong-2e"
+pmon_yeeloong_str:	.asciz "PMON_VER=LM8"
+pmon_fuloong2f_str:	.asciz "PMON_VER=LM6"
+pmon_yeeloong_verstr:	.asciz "Version=LM8"
+pmon_fuloong2f_verstr:	.asciz "Version=LM6"
 	.p2align 2
 
 argdone:
diff --git a/grub-core/boot/sparc64/ieee1275/boot.S b/grub-core/boot/sparc64/ieee1275/boot.S
index 507367749..586efb401 100644
--- a/grub-core/boot/sparc64/ieee1275/boot.S
+++ b/grub-core/boot/sparc64/ieee1275/boot.S
@@ -41,9 +41,9 @@ pic_base:
 	 * After loading in that block we will execute it by jumping to the
 	 * load address plus the size of the prepended A.OUT header (32 bytes).
 	 */
-	. = _start + GRUB_BOOT_MACHINE_BOOT_DEVPATH
+	.org GRUB_BOOT_MACHINE_BOOT_DEVPATH
 boot_path:
-	. = _start + GRUB_BOOT_MACHINE_KERNEL_BYTE
+	.org GRUB_BOOT_MACHINE_KERNEL_BYTE
 boot_path_end:
 kernel_byte:		.xword (2 << 9)
 kernel_address:		.word  GRUB_BOOT_MACHINE_KERNEL_ADDR
@@ -52,7 +52,7 @@ kernel_address:		.word  GRUB_BOOT_MACHINE_KERNEL_ADDR
 #define boot_path_end (_start + 1024)
 #include <grub/offsets.h>
 
-	. = _start + 8
+	.org 8
 kernel_byte:		.xword (2 << 9)
 kernel_size:	        .word  512
 kernel_address:		.word  GRUB_BOOT_SPARC64_IEEE1275_IMAGE_ADDRESS
@@ -224,7 +224,7 @@ bootpath_known:
 #else
 	 nop
 #endif
-	. = _start + GRUB_BOOT_MACHINE_CODE_END
+	.org GRUB_BOOT_MACHINE_CODE_END
 
 /* the last 4 bytes in the sector 0 contain the signature */
 	.word	GRUB_BOOT_MACHINE_SIGNATURE
diff --git a/grub-core/boot/sparc64/ieee1275/diskboot.S b/grub-core/boot/sparc64/ieee1275/diskboot.S
index e020f6221..35e02c1b6 100644
--- a/grub-core/boot/sparc64/ieee1275/diskboot.S
+++ b/grub-core/boot/sparc64/ieee1275/diskboot.S
@@ -136,7 +136,7 @@ lastlist:
 	.word	0
 	.word	0
 
-	. = _start + (0x200 - GRUB_BOOT_SPARC64_IEEE1275_LIST_SIZE)
+	.org (0x200 - GRUB_BOOT_SPARC64_IEEE1275_LIST_SIZE)
 blocklist_default_start:
 	.word	0
 	.word	2
diff --git a/grub-core/bus/emu/pci.c b/grub-core/bus/emu/pci.c
index 9d3296395..663e5540c 100644
--- a/grub-core/bus/emu/pci.c
+++ b/grub-core/bus/emu/pci.c
@@ -55,7 +55,8 @@ grub_pci_device_map_range (grub_pci_device_t dev, grub_addr_t base,
   int err;
   err = pci_device_map_range (dev, base, size, PCI_DEV_MAP_FLAG_WRITABLE, &addr);
   if (err)
-    grub_util_error ("mapping 0x%x failed (error %d)\n", base, err);
+    grub_util_error ("mapping 0x%llx failed (error %d)\n",
+		     (unsigned long long) base, err);
   return addr;
 }
 
@@ -66,12 +67,12 @@ grub_pci_device_unmap_range (grub_pci_device_t dev, void *mem,
   pci_device_unmap_range (dev, mem, size);
 }
 
-GRUB_MOD_INIT (pci)
+GRUB_MOD_INIT (emupci)
 {
   pci_system_init ();
 }
 
-GRUB_MOD_FINI (pci)
+GRUB_MOD_FINI (emupci)
 {
   pci_system_cleanup ();
 }
diff --git a/grub-core/bus/usb/emu/usb.c b/grub-core/bus/usb/emu/usb.c
deleted file mode 100644
index 3ad2fc312..000000000
--- a/grub-core/bus/usb/emu/usb.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/*  usb.c -- libusb USB support for GRUB.  */
-/*
- *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 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 <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-#include <grub/misc.h>
-#include <grub/mm.h>
-#include <usb.h>
-#include <grub/usb.h>
-#include <grub/dl.h>
-
-GRUB_MOD_LICENSE ("GPLv3+");
-
-
-static struct grub_usb_controller_dev usb_controller =
-{
-  .name = "libusb"
-};
-
-static struct grub_usb_device *grub_usb_devs[128];
-
-struct usb_bus *busses;
-
-static grub_err_t
-grub_libusb_devices (void)
-
-{
-  struct usb_bus *bus;
-  int last = 0;
-
-  busses = usb_get_busses();
-
-  for (bus = busses; bus; bus = bus->next)
-    {
-      struct usb_device *usbdev;
-      struct grub_usb_device *dev;
-
-      for (usbdev = bus->devices; usbdev; usbdev = usbdev->next)
-	{
-	  struct usb_device_descriptor *desc = &usbdev->descriptor;
-	  grub_err_t err;
-
-	  if (! desc->bcdUSB)
-	    continue;
-
-	  dev = grub_malloc (sizeof (*dev));
-	  if (! dev)
-	    return grub_errno;
-
-	  dev->data = usbdev;
-
-	  /* Fill in all descriptors.  */
-	  err = grub_usb_device_initialize (dev);
-	  if (err)
-	    {
-	      grub_errno = GRUB_ERR_NONE;
-	      continue;
-	    }
-
-	  /* Register the device.  */
-	  grub_usb_devs[last++] = dev;
-	}
-    }
-
-  return GRUB_USB_ERR_NONE;
-}
-
-void
-grub_usb_poll_devices (void)
-{
-  /* TODO: recheck grub_usb_devs */
-}
-
-
-int
-grub_usb_iterate (grub_usb_iterate_hook_t hook, void *hook_data)
-{
-  int i;
-
-  for (i = 0; i < 128; i++)
-    {
-      if (grub_usb_devs[i])
-	{
-	  if (hook (grub_usb_devs[i], hook_data))
-	      return 1;
-	}
-    }
-
-  return 0;
-}
-
-grub_usb_err_t
-grub_usb_root_hub (grub_usb_controller_t controller __attribute__((unused)))
-{
-  return GRUB_USB_ERR_NONE;
-}
-
-grub_usb_err_t
-grub_usb_control_msg (grub_usb_device_t dev, grub_uint8_t reqtype,
-		      grub_uint8_t request, grub_uint16_t value,
-		      grub_uint16_t idx, grub_size_t size, char *data)
-{
-  usb_dev_handle *devh;
-  struct usb_device *d = dev->data;
-
-  devh = usb_open (d);
-  if (usb_control_msg (devh, reqtype, request,
-		       value, idx, data, size, 20) < 0)
-    {
-      usb_close (devh);
-      return GRUB_USB_ERR_STALL;
-    }
-
-  usb_close (devh);
-
-  return GRUB_USB_ERR_NONE;
-}
-
-grub_usb_err_t
-grub_usb_bulk_read (grub_usb_device_t dev,
-		    int endpoint, grub_size_t size, char *data)
-{
-  usb_dev_handle *devh;
-  struct usb_device *d = dev->data;
-
-  devh = usb_open (d);
-  if (usb_claim_interface (devh, 0) < 1)
-    {
-      usb_close (devh);
-      return GRUB_USB_ERR_STALL;
-    }
-
-  if (usb_bulk_read (devh, endpoint, data, size, 20) < 1)
-    {
-      usb_close (devh);
-      return GRUB_USB_ERR_STALL;
-    }
-
-  usb_release_interface (devh, 0);
-  usb_close (devh);
-
-  return GRUB_USB_ERR_NONE;
-}
-
-grub_usb_err_t
-grub_usb_bulk_write (grub_usb_device_t dev,
-		     int endpoint, grub_size_t size, char *data)
-{
-  usb_dev_handle *devh;
-  struct usb_device *d = dev->data;
-
-  devh = usb_open (d);
-  if (usb_claim_interface (devh, 0) < 0)
-    goto fail;
-
-  if (usb_bulk_write (devh, endpoint, data, size, 20) < 0)
-    goto fail;
-
-  if (usb_release_interface (devh, 0) < 0)
-    goto fail;
-
-  usb_close (devh);
-
-  return GRUB_USB_ERR_NONE;
-
- fail:
-  usb_close (devh);
-  return GRUB_USB_ERR_STALL;
-}
-
-GRUB_MOD_INIT (libusb)
-{
-  usb_init();
-  usb_find_busses();
-  usb_find_devices();
-
-  if (grub_libusb_devices ())
-    return;
-
-  grub_usb_controller_dev_register (&usb_controller);
-
-  return;
-}
-
-GRUB_MOD_FINI (libusb)
-{
-  return;
-}
diff --git a/grub-core/bus/usb/uhci.c b/grub-core/bus/usb/uhci.c
index a95fdfe07..7c5811fd6 100644
--- a/grub-core/bus/usb/uhci.c
+++ b/grub-core/bus/usb/uhci.c
@@ -625,9 +625,7 @@ grub_uhci_check_transfer (grub_usb_controller_t dev,
       return GRUB_USB_ERR_NONE;
     }
 
-  grub_dprintf ("uhci", "t status=0x%02x\n", errtd->ctrl_status);
-
-  if (!(errtd->ctrl_status & (1 << 23)))
+  if (errtd && !(errtd->ctrl_status & (1 << 23)))
     {
       grub_usb_err_t err = GRUB_USB_ERR_NONE;
 
diff --git a/grub-core/bus/usb/usbtrans.c b/grub-core/bus/usb/usbtrans.c
index 557e71c2e..b614997f2 100644
--- a/grub-core/bus/usb/usbtrans.c
+++ b/grub-core/bus/usb/usbtrans.c
@@ -31,7 +31,7 @@ grub_usb_bulk_maxpacket (grub_usb_device_t dev,
 			 struct grub_usb_desc_endp *endpoint)
 {
   /* Use the maximum packet size given in the endpoint descriptor.  */
-  if (dev->initialized && endpoint)
+  if (dev->initialized && endpoint && (unsigned int) endpoint->maxpacket)
     return endpoint->maxpacket;
 
   return 64;
diff --git a/grub-core/commands/acpi.c b/grub-core/commands/acpi.c
index 97c2cf282..05a6dcad4 100644
--- a/grub-core/commands/acpi.c
+++ b/grub-core/commands/acpi.c
@@ -131,6 +131,8 @@ grub_acpi_get_rsdpv1 (void)
   return grub_machine_acpi_get_rsdpv1 ();
 }
 
+#if defined (__i386__) || defined (__x86_64__)
+
 static inline int
 iszero (grub_uint8_t *reg, int size)
 {
@@ -141,7 +143,6 @@ iszero (grub_uint8_t *reg, int size)
   return 1;
 }
 
-#if defined (__i386__) || defined (__x86_64__)
 /* Context for grub_acpi_create_ebda.  */
 struct grub_acpi_create_ebda_ctx {
   int ebda_len;
@@ -227,7 +228,7 @@ grub_acpi_create_ebda (void)
 	    grub_dprintf ("acpi", "Copying rsdpv2 to %p\n", target);
 	    v2inebda = target;
 	    target += v2->length;
-	    target = (grub_uint8_t *) ((((grub_addr_t) target - 1) | 0xf) + 1);
+	    target = (grub_uint8_t *) ALIGN_UP((grub_addr_t) target, 16);
 	    v2 = 0;
 	    break;
 	  }
@@ -246,7 +247,7 @@ grub_acpi_create_ebda (void)
 	    grub_dprintf ("acpi", "Copying rsdpv1 to %p\n", target);
 	    v1inebda = target;
 	    target += sizeof (struct grub_acpi_rsdp_v10);
-	    target = (grub_uint8_t *) ((((grub_addr_t) target - 1) | 0xf) + 1);
+	    target = (grub_uint8_t *) ALIGN_UP((grub_addr_t) target, 16);
 	    v1 = 0;
 	    break;
 	  }
@@ -265,7 +266,7 @@ grub_acpi_create_ebda (void)
 	    grub_memcpy (target, v2, v2->length);
 	    v2inebda = target;
 	    target += v2->length;
-	    target = (grub_uint8_t *) ((((grub_addr_t) target - 1) | 0xf) + 1);
+	    target = (grub_uint8_t *) ALIGN_UP((grub_addr_t) target, 16);
 	    v2 = 0;
 	    break;
 	  }
@@ -282,7 +283,7 @@ grub_acpi_create_ebda (void)
 	    grub_memcpy (target, v1, sizeof (struct grub_acpi_rsdp_v10));
 	    v1inebda = target;
 	    target += sizeof (struct grub_acpi_rsdp_v10);
-	    target = (grub_uint8_t *) ((((grub_addr_t) target - 1) | 0xf) + 1);
+	    target = (grub_uint8_t *) ALIGN_UP((grub_addr_t) target, 16);
 	    v1 = 0;
 	    break;
 	  }
diff --git a/grub-core/commands/cacheinfo.c b/grub-core/commands/cacheinfo.c
index ead6ff82c..d34a34696 100644
--- a/grub-core/commands/cacheinfo.c
+++ b/grub-core/commands/cacheinfo.c
@@ -23,6 +23,8 @@
 #include <grub/i18n.h>
 #include <grub/disk.h>
 
+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/grub-core/commands/file.c b/grub-core/commands/file.c
index 42d62d479..12fba99e0 100644
--- a/grub-core/commands/file.c
+++ b/grub-core/commands/file.c
@@ -476,8 +476,8 @@ grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args)
 	   be at least 12 bytes and aligned on a 4-byte boundary.  */
 	for (header = buffer;
 	     ((char *) header <=
-	      (char *) buffer + len - (type == IS_MULTIBOOT2 ? 16 : 12))
-	     || (header = 0); header += step)
+	      (char *) buffer + len - (type == IS_MULTIBOOT2 ? 16 : 12));
+	     header += step)
 	  {
 	    if (header[0] == magic
 		&& !(grub_le_to_cpu32 (header[0])
@@ -485,11 +485,12 @@ grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args)
 		     + grub_le_to_cpu32 (header[2])
 		     + (type == IS_MULTIBOOT2
 			? grub_le_to_cpu32 (header[3]) : 0)))
-	      break;
+	      {
+		ret = 1;
+		break;
+	      }
 	  }
 
-	if (header != 0)
-	  ret = 1;
 	grub_free (buffer);
 	break;
       }
diff --git a/grub-core/commands/fileXX.c b/grub-core/commands/fileXX.c
index 58e1094c6..c17d26ce6 100644
--- a/grub-core/commands/fileXX.c
+++ b/grub-core/commands/fileXX.c
@@ -40,10 +40,10 @@ grub_file_check_netbsdXX (grub_elf_t elf)
     return 0;
 
   if (grub_file_seek (elf->file, elf->ehdr.ehdrXX.e_shoff) == (grub_off_t) -1)
-    return 0;
+    goto fail;
 
   if (grub_file_read (elf->file, s0, shsize) != (grub_ssize_t) shsize)
-    return 0;
+    goto fail;
 
   s = (Elf_Shdr *) ((char *) s0 + elf->ehdr.ehdrXX.e_shstrndx * shentsize);
   stroff = s->sh_offset;
@@ -54,18 +54,21 @@ grub_file_check_netbsdXX (grub_elf_t elf)
       char name[sizeof(".note.netbsd.ident")];
       grub_memset (name, 0, sizeof (name));
       if (grub_file_seek (elf->file, stroff + s->sh_name) == (grub_off_t) -1)
-	return grub_errno;
+	goto fail;
 
       if (grub_file_read (elf->file, name, sizeof (name)) != (grub_ssize_t) sizeof (name))
 	{
 	  if (grub_errno)
-	    return grub_errno;
+	    goto fail;
 	  continue;
 	}
       if (grub_memcmp (name, ".note.netbsd.ident",
 		       sizeof(".note.netbsd.ident")) != 0)
 	continue;
+      grub_free (s0);
       return 1;
     }
+ fail:
+  grub_free (s0);
   return 0;
 }
diff --git a/grub-core/commands/gptsync.c b/grub-core/commands/gptsync.c
index 16592e9bb..444e24874 100644
--- a/grub-core/commands/gptsync.c
+++ b/grub-core/commands/gptsync.c
@@ -235,6 +235,8 @@ grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)),
       return grub_errno;
     }
 
+  grub_device_close (dev);
+
   grub_printf_ (N_("New MBR is written to `%s'\n"), args[0]);
 
   return GRUB_ERR_NONE;
diff --git a/grub-core/commands/hdparm.c b/grub-core/commands/hdparm.c
index 3fb08912d..f6b178eae 100644
--- a/grub-core/commands/hdparm.c
+++ b/grub-core/commands/hdparm.c
@@ -329,6 +329,7 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args)
 	  break;
 	}
     default:
+      grub_disk_close (disk);
       return grub_error (GRUB_ERR_IO, "not an ATA device");
     }
     
diff --git a/grub-core/commands/i386/pc/play.c b/grub-core/commands/i386/pc/play.c
index 40798c96c..7712e2a36 100644
--- a/grub-core/commands/i386/pc/play.c
+++ b/grub-core/commands/i386/pc/play.c
@@ -107,6 +107,14 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)),
           return grub_errno;
         }
 
+      if (!tempo)
+        {
+          grub_file_close (file);
+	  grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Invalid tempo in %s"),
+		      args[0]);
+          return grub_errno;
+        }
+
       tempo = grub_le_to_cpu32 (tempo);
       grub_dprintf ("play","tempo = %d\n", tempo);
 
@@ -131,6 +139,13 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)),
 
       tempo = grub_strtoul (args[0], &end, 0);
 
+      if (!tempo)
+        {
+	  grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Invalid tempo in %s"),
+		      args[0]);
+          return grub_errno;
+        }
+
       if (*end)
         /* Was not a number either, assume it was supposed to be a file name.  */
         return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), args[0]);
diff --git a/grub-core/commands/i386/pc/sendkey.c b/grub-core/commands/i386/pc/sendkey.c
index d985cb33f..26d9acd3d 100644
--- a/grub-core/commands/i386/pc/sendkey.c
+++ b/grub-core/commands/i386/pc/sendkey.c
@@ -292,7 +292,7 @@ find_key_code (char *key)
 {
   unsigned i;
 
-  for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++)
+  for (i = 0; i < ARRAY_SIZE(keysym_table); i++)
     {
       if (keysym_table[i].unshifted_name 
 	  && grub_strcmp (key, keysym_table[i].unshifted_name) == 0)
@@ -311,7 +311,7 @@ find_ascii_code (char *key)
 {
   unsigned i;
 
-  for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++)
+  for (i = 0; i < ARRAY_SIZE(keysym_table); i++)
     {
       if (keysym_table[i].unshifted_name 
 	  && grub_strcmp (key, keysym_table[i].unshifted_name) == 0)
@@ -352,15 +352,13 @@ grub_cmd_sendkey (grub_extcmd_context_t ctxt, int argc, char **args)
 
   {
     unsigned i;
-    for (i = 0; i < sizeof (simple_flag_offsets) 
-	   / sizeof (simple_flag_offsets[0]); i++)
+    for (i = 0; i < ARRAY_SIZE(simple_flag_offsets); i++)
       grub_sendkey_set_simple_flag (simple_flag_offsets[i], 
 				    grub_sendkey_parse_op(state[i]));
   }
 
   /* Set noled. */
-  noled = (state[sizeof (simple_flag_offsets) 
-		 / sizeof (simple_flag_offsets[0])].set);
+  noled = (state[ARRAY_SIZE(simple_flag_offsets)].set);
 
   return GRUB_ERR_NONE;
 }
diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c
index 2c09fb7dd..d42d7779e 100644
--- a/grub-core/commands/legacycfg.c
+++ b/grub-core/commands/legacycfg.c
@@ -57,14 +57,20 @@ legacy_file (const char *filename)
 
   file = grub_file_open (filename);
   if (! file)
-    return grub_errno;
+    {
+      grub_free (suffix);
+      return grub_errno;
+    }
 
   menu = grub_env_get_menu ();
   if (! menu)
     {
       menu = grub_zalloc (sizeof (*menu));
       if (! menu)
-	return grub_errno;
+	{
+	  grub_free (suffix);
+	  return grub_errno;
+	}
 
       grub_env_set_menu (menu);
     }
@@ -77,6 +83,7 @@ legacy_file (const char *filename)
       if (!buf && grub_errno)
 	{
 	  grub_file_close (file);
+	  grub_free (suffix);
 	  return grub_errno;
 	}
 
@@ -173,6 +180,8 @@ legacy_file (const char *filename)
       if (!args)
 	{
 	  grub_file_close (file);
+	  grub_free (suffix);
+	  grub_free (entrysrc);
 	  return grub_errno;
 	}
       args[0] = entryname;
@@ -376,6 +385,8 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
 	      if (part && grub_strcmp (part->partmap->name, "msdos") == 0)
 		bsd_slice = part->number;
 	    }
+	  if (dev)
+	    grub_device_close (dev);
 	}
 	
 	/* k*BSD didn't really work well with grub-legacy.  */
diff --git a/grub-core/commands/macbless.c b/grub-core/commands/macbless.c
index 4724edd77..18efa1a84 100644
--- a/grub-core/commands/macbless.c
+++ b/grub-core/commands/macbless.c
@@ -106,7 +106,7 @@ grub_mac_bless_inode (grub_device_t dev, grub_uint32_t inode, int is_dir,
       ablk_size = grub_be_to_cpu32 (volheader.hfs.blksz);
       ablk_start = grub_be_to_cpu16 (volheader.hfs.first_block);
       embedded_offset = (ablk_start
-			 + extent_start
+			 + ((grub_uint64_t) extent_start)
 			 * (ablk_size >> GRUB_DISK_SECTOR_BITS));
 
       err =
@@ -183,7 +183,7 @@ grub_cmd_macbless (grub_command_t cmd, int argc, char **args)
 {
   char *device_name;
   char *path = 0;
-  grub_device_t dev;
+  grub_device_t dev = 0;
   grub_err_t err;
 
   if (argc != 1)
@@ -197,13 +197,12 @@ grub_cmd_macbless (grub_command_t cmd, int argc, char **args)
   else
     path = path + 1;
 
-  if (!path || *path == 0 || !device_name)
+  if (!path || *path == 0 || !dev)
     {
       if (dev)
 	grub_device_close (dev);
 
       grub_free (device_name);
-      grub_free (path);
 
       return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid argument");
     }
diff --git a/grub-core/commands/nativedisk.c b/grub-core/commands/nativedisk.c
index 33b6b99ea..b3bc4639c 100644
--- a/grub-core/commands/nativedisk.c
+++ b/grub-core/commands/nativedisk.c
@@ -57,6 +57,7 @@ get_uuid (const char *name, char **uuid, int getnative)
   if (!dev->disk)
     {
       grub_dprintf ("nativedisk", "Skipping non-disk\n");
+      grub_device_close (dev);
       return 0;
     }
 
@@ -90,6 +91,7 @@ get_uuid (const char *name, char **uuid, int getnative)
     case GRUB_DISK_DEVICE_MEMDISK_ID:
       grub_dprintf ("nativedisk", "Skipping native disk %s\n",
 		    dev->disk->name);
+      grub_device_close (dev);
       return 0;
 
       /* FIXME: those probably need special handling.  */
diff --git a/grub-core/commands/parttool.c b/grub-core/commands/parttool.c
index a47ff0776..42c590e1a 100644
--- a/grub-core/commands/parttool.c
+++ b/grub-core/commands/parttool.c
@@ -243,11 +243,19 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
   }
 
   if (argc == 1)
-    return show_help (dev);
+    {
+      err = show_help (dev);
+      grub_device_close (dev);
+      return err;
+    }
 
   for (i = 1; i < argc; i++)
     if (grub_strcmp (args[i], "help") == 0)
-      return show_help (dev);
+      {
+	err = show_help (dev);
+	grub_device_close (dev);
+	return err;
+      }
 
   parsed = (int *) grub_zalloc (argc * sizeof (int));
 
@@ -274,8 +282,11 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
 		break;
 	    }
 	if (! cur)
-	  return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unknown argument `%s'"),
+	  {
+	    grub_device_close (dev);
+	    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unknown argument `%s'"),
 			     args[i]);
+	  }
 	ptool = cur;
 	pargs = (struct grub_parttool_args *)
 	  grub_zalloc (ptool->nargs * sizeof (struct grub_parttool_args));
diff --git a/grub-core/commands/syslinuxcfg.c b/grub-core/commands/syslinuxcfg.c
index 00ae113c5..7be28fada 100644
--- a/grub-core/commands/syslinuxcfg.c
+++ b/grub-core/commands/syslinuxcfg.c
@@ -119,7 +119,10 @@ syslinux_file (grub_extcmd_context_t ctxt, const char *filename)
     {
       menu = grub_zalloc (sizeof (*menu));
       if (! menu)
-	return grub_errno;
+	{
+	  grub_free (result);
+	  return grub_errno;
+	}
 
       grub_env_set_menu (menu);
     }
diff --git a/grub-core/commands/test.c b/grub-core/commands/test.c
index c98c13d8c..5f06642f6 100644
--- a/grub-core/commands/test.c
+++ b/grub-core/commands/test.c
@@ -332,7 +332,7 @@ test_parse (char **args, int *argn, int argc)
 	      get_fileinfo (args[*argn + 1], &ctx);
 	      update_val (ctx.file_exists && ctx.file_info.dir, &ctx);
 	      (*argn) += 2;
-	      return ctx.or || ctx.and;
+	      continue;
 	    }
 
 	  if (grub_strcmp (args[*argn], "-e") == 0)
@@ -340,7 +340,7 @@ test_parse (char **args, int *argn, int argc)
 	      get_fileinfo (args[*argn + 1], &ctx);
 	      update_val (ctx.file_exists, &ctx);
 	      (*argn) += 2;
-	      return ctx.or || ctx.and;
+	      continue;
 	    }
 
 	  if (grub_strcmp (args[*argn], "-f") == 0)
@@ -349,7 +349,7 @@ test_parse (char **args, int *argn, int argc)
 	      /* FIXME: check for other types. */
 	      update_val (ctx.file_exists && ! ctx.file_info.dir, &ctx);
 	      (*argn) += 2;
-	      return ctx.or || ctx.and;
+	      continue;
 	    }
 
 	  if (grub_strcmp (args[*argn], "-s") == 0)
@@ -362,7 +362,7 @@ test_parse (char **args, int *argn, int argc)
 		grub_file_close (file);
 	      grub_errno = GRUB_ERR_NONE;
 	      (*argn) += 2;
-	      return ctx.or || ctx.and;
+	      continue;
 	    }
 
 	  /* String tests. */
diff --git a/grub-core/commands/tr.c b/grub-core/commands/tr.c
index 84ad6ff8f..ef72841a2 100644
--- a/grub-core/commands/tr.c
+++ b/grub-core/commands/tr.c
@@ -80,7 +80,7 @@ grub_cmd_tr (grub_extcmd_context_t ctxt, int argc, char **args)
   } else if (argc > 3)
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "too many parameters");
 
-  if (argc <= 0 && (!s1 || !s2 || !input))
+  if (!s1 || !s2 || !input)
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing parameters");
 
   if (grub_strlen (s1) != grub_strlen (s2))
diff --git a/grub-core/commands/verify.c b/grub-core/commands/verify.c
index 525bdd187..9620a3b4c 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
@@ -301,7 +308,7 @@ grub_load_public_key (grub_file_t f)
       if (!sk)
 	goto fail;
 
-      grub_memset (fingerprint_context, 0, sizeof (fingerprint_context));
+      grub_memset (fingerprint_context, 0, GRUB_MD_SHA1->contextsize);
       GRUB_MD_SHA1->init (fingerprint_context);
       GRUB_MD_SHA1->write (fingerprint_context, "\x99", 1);
       len_be = grub_cpu_to_be16 (len);
@@ -447,7 +454,7 @@ grub_verify_signature_real (char *buf, grub_size_t size,
   grub_err_t err;
   grub_size_t i;
   gcry_mpi_t mpis[10];
-  grub_uint8_t type;
+  grub_uint8_t type = 0;
 
   err = read_packet_header (sig, &type, &len);
   if (err)
@@ -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");
-      return NULL;
-    }
-  ret->data = grub_malloc (ret->size);
-  if (!ret->data)
-    {
+      grub_file_close (sig);
       grub_free (ret);
       return NULL;
     }
-  if (grub_file_read (io, ret->data, ret->size) != (grub_ssize_t) ret->size)
+  verified = grub_malloc (sizeof (*verified));
+  if (!verified)
+    {
+      grub_file_close (sig);
+      grub_free (ret);
+      return NULL;
+    }
+  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, 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/grub-core/commands/wildcard.c b/grub-core/commands/wildcard.c
index 2807f806b..9b4e72766 100644
--- a/grub-core/commands/wildcard.c
+++ b/grub-core/commands/wildcard.c
@@ -245,7 +245,10 @@ match_devices_iter (const char *name, void *data)
 
   t = grub_realloc (ctx->devs, sizeof (char*) * (ctx->ndev + 2));
   if (! t)
-    return 1;
+    {
+      grub_free (buffer);
+      return 1;
+    }
 
   ctx->devs = t;
   ctx->devs[ctx->ndev++] = buffer;
@@ -290,7 +293,8 @@ struct match_files_ctx
 
 /* Helper for match_files.  */
 static int
-match_files_iter (const char *name, const struct grub_dirhook_info *info,
+match_files_iter (const char *name,
+		  const struct grub_dirhook_info *info __attribute__((unused)),
 		  void *data)
 {
   struct match_files_ctx *ctx = data;
diff --git a/grub-core/disk/AFSplitter.c b/grub-core/disk/AFSplitter.c
index d76a1c447..f5a8ddc61 100644
--- a/grub-core/disk/AFSplitter.c
+++ b/grub-core/disk/AFSplitter.c
@@ -72,13 +72,13 @@ AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src, grub_uint8_t * dst,
   grub_size_t i;
   grub_uint8_t *bufblock;
 
+  if (hash->mdlen > GRUB_CRYPTO_MAX_MDLEN || hash->mdlen == 0)
+    return GPG_ERR_INV_ARG;
+
   bufblock = grub_zalloc (blocksize);
   if (bufblock == NULL)
     return GPG_ERR_OUT_OF_MEMORY;
 
-  if (hash->mdlen > GRUB_CRYPTO_MAX_MDLEN)
-    return GPG_ERR_INV_ARG;
-
   grub_memset (bufblock, 0, blocksize);
   for (i = 0; i < blocknumbers - 1; i++)
     {
diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c
index 89365cd09..d6bdbddf6 100644
--- a/grub-core/disk/ahci.c
+++ b/grub-core/disk/ahci.c
@@ -198,7 +198,7 @@ grub_ahci_pciinit (grub_pci_device_t dev,
 		    | GRUB_PCI_COMMAND_MEM_ENABLED);
 
   hba = grub_pci_device_map_range (dev, bar & GRUB_PCI_ADDR_MEM_MASK,
-				   sizeof (hba));
+				   sizeof (*hba));
   grub_dprintf ("ahci", "dev: %x:%x.%x\n", dev.bus, dev.device, dev.function);
 
   grub_dprintf ("ahci", "tfd[0]: %x\n",
diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c
index 2b988490f..8ba4e5c50 100644
--- a/grub-core/disk/ata.c
+++ b/grub-core/disk/ata.c
@@ -216,6 +216,12 @@ grub_ata_setaddress (struct grub_ata *dev,
 	unsigned int head;
 	unsigned int sect;
 
+	if (dev->sectors_per_track == 0
+	    || dev->heads == 0)
+	  return grub_error (GRUB_ERR_OUT_OF_RANGE,
+			     "sector %d cannot be addressed "
+			     "using CHS addressing", sector);
+
 	/* Calculate the sector, cylinder and head to use.  */
 	sect = ((grub_uint32_t) sector % dev->sectors_per_track) + 1;
 	cylinder = (((grub_uint32_t) sector / dev->sectors_per_track)
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index f0e3a900a..82a3dcb63 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -110,20 +110,23 @@ grub_crypto_pcbc_decrypt (grub_crypto_cipher_handle_t cipher,
 {
   grub_uint8_t *inptr, *outptr, *end;
   grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE];
-  if (cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
-    return GPG_ERR_INV_ARG;
+  grub_size_t blocksize;
   if (!cipher->cipher->decrypt)
     return GPG_ERR_NOT_SUPPORTED;
-  if (size % cipher->cipher->blocksize != 0)
+  blocksize = cipher->cipher->blocksize;
+  if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
+      || ((size & (blocksize - 1)) != 0))
+    return GPG_ERR_INV_ARG;
+  if (blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
     return GPG_ERR_INV_ARG;
   end = (grub_uint8_t *) in + size;
   for (inptr = in, outptr = out; inptr < end;
-       inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
+       inptr += blocksize, outptr += blocksize)
     {
-      grub_memcpy (ivt, inptr, cipher->cipher->blocksize);
+      grub_memcpy (ivt, inptr, blocksize);
       cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
-      grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize);
-      grub_crypto_xor (iv, ivt, outptr, cipher->cipher->blocksize);
+      grub_crypto_xor (outptr, outptr, iv, blocksize);
+      grub_crypto_xor (iv, ivt, outptr, blocksize);
     }
   return GPG_ERR_NO_ERROR;
 }
@@ -135,20 +138,23 @@ grub_crypto_pcbc_encrypt (grub_crypto_cipher_handle_t cipher,
 {
   grub_uint8_t *inptr, *outptr, *end;
   grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE];
-  if (cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
-    return GPG_ERR_INV_ARG;
-  if (!cipher->cipher->decrypt)
+  grub_size_t blocksize;
+  if (!cipher->cipher->encrypt)
     return GPG_ERR_NOT_SUPPORTED;
-  if (size % cipher->cipher->blocksize != 0)
+  blocksize = cipher->cipher->blocksize;
+  if (blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
+    return GPG_ERR_INV_ARG;
+  if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
+      || ((size & (blocksize - 1)) != 0))
     return GPG_ERR_INV_ARG;
   end = (grub_uint8_t *) in + size;
   for (inptr = in, outptr = out; inptr < end;
-       inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
+       inptr += blocksize, outptr += blocksize)
     {
-      grub_memcpy (ivt, inptr, cipher->cipher->blocksize);
-      grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize);
+      grub_memcpy (ivt, inptr, blocksize);
+      grub_crypto_xor (outptr, outptr, iv, blocksize);
       cipher->cipher->encrypt (cipher->ctx, outptr, inptr);
-      grub_crypto_xor (iv, ivt, outptr, cipher->cipher->blocksize);
+      grub_crypto_xor (iv, ivt, outptr, blocksize);
     }
   return GPG_ERR_NO_ERROR;
 }
@@ -372,11 +378,13 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	  break;
 	case GRUB_CRYPTODISK_MODE_ECB:
 	  if (do_encrypt)
-	    grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i,
-				     (1U << dev->log_sector_size));
+	    err = grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i,
+					   (1U << dev->log_sector_size));
 	  else
-	    grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
-				     (1U << dev->log_sector_size));
+	    err = grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
+					   (1U << dev->log_sector_size));
+	  if (err)
+	    return err;
 	  break;
 	default:
 	  return GPG_ERR_NOT_IMPLEMENTED;
diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c
index e8a3bcbd1..c4f6678b6 100644
--- a/grub-core/disk/diskfilter.c
+++ b/grub-core/disk/diskfilter.c
@@ -71,10 +71,12 @@ is_lv_readable (struct grub_diskfilter_lv *lv, int easily)
 	case GRUB_DISKFILTER_RAID6:
 	  if (!easily)
 	    need--;
+	  /* Fallthrough.  */
 	case GRUB_DISKFILTER_RAID4:
 	case GRUB_DISKFILTER_RAID5:
 	  if (!easily)
 	    need--;
+	  /* Fallthrough.  */
 	case GRUB_DISKFILTER_STRIPED:
 	  break;
 
@@ -483,6 +485,96 @@ grub_diskfilter_read_node (const struct grub_diskfilter_node *node,
   return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown node '%s'", node->name);
 }
 
+
+static grub_err_t
+validate_segment (struct grub_diskfilter_segment *seg);
+
+static grub_err_t
+validate_lv (struct grub_diskfilter_lv *lv)
+{
+  unsigned int i;
+  if (!lv)
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown volume");
+
+  if (!lv->vg || lv->vg->extent_size == 0)
+    return grub_error (GRUB_ERR_READ_ERROR, "invalid volume");
+
+  for (i = 0; i < lv->segment_count; i++)
+    {
+      grub_err_t err;
+      err = validate_segment (&lv->segments[i]);
+      if (err)
+	return err;
+    }
+  return GRUB_ERR_NONE;
+}
+
+
+static grub_err_t
+validate_node (const struct grub_diskfilter_node *node)
+{
+  /* Check whether we actually know the physical volume we want to
+     read from.  */
+  if (node->pv)
+    return GRUB_ERR_NONE;
+  if (node->lv)
+    return validate_lv (node->lv);
+  return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown node '%s'", node->name);
+}
+
+static grub_err_t
+validate_segment (struct grub_diskfilter_segment *seg)
+{
+  grub_err_t err;
+
+  if (seg->stripe_size == 0 || seg->node_count == 0)
+    return grub_error(GRUB_ERR_BAD_FS, "invalid segment");
+
+  switch (seg->type)
+    {
+    case GRUB_DISKFILTER_RAID10:
+      {
+	grub_uint8_t near, far;
+	near = seg->layout & 0xFF;
+	far = (seg->layout >> 8) & 0xFF;
+	if ((seg->layout >> 16) == 0 && far == 0)
+	  return grub_error(GRUB_ERR_BAD_FS, "invalid segment");
+	if (near > seg->node_count)
+	  return grub_error(GRUB_ERR_BAD_FS, "invalid segment");
+	break;
+      }
+
+    case GRUB_DISKFILTER_STRIPED:
+    case GRUB_DISKFILTER_MIRROR:
+	break;
+
+    case GRUB_DISKFILTER_RAID4:
+    case GRUB_DISKFILTER_RAID5:
+      if (seg->node_count <= 1)
+	return grub_error(GRUB_ERR_BAD_FS, "invalid segment");
+      break;
+
+    case GRUB_DISKFILTER_RAID6:
+      if (seg->node_count <= 2)
+	return grub_error(GRUB_ERR_BAD_FS, "invalid segment");
+      break;
+
+    default:
+      return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+			 "unsupported RAID level %d", seg->type);
+    }
+
+  unsigned i;
+  for (i = 0; i < seg->node_count; i++)
+    {
+      err = validate_node (&seg->nodes[i]);
+      if (err)
+	return err;
+    }
+  return GRUB_ERR_NONE;
+
+}
+
 static grub_err_t
 read_segment (struct grub_diskfilter_segment *seg, grub_disk_addr_t sector,
 	      grub_size_t size, char *buf)
@@ -494,6 +586,7 @@ read_segment (struct grub_diskfilter_segment *seg, grub_disk_addr_t sector,
       if (seg->node_count == 1)
 	return grub_diskfilter_read_node (&seg->nodes[0],
 					  sector, size, buf);
+      /* Fallthrough.  */
     case GRUB_DISKFILTER_MIRROR:
     case GRUB_DISKFILTER_RAID10:
       {
@@ -848,6 +941,23 @@ grub_diskfilter_vg_register (struct grub_diskfilter_vg *vg)
 
   for (lv = vg->lvs; lv; lv = lv->next)
     {
+      grub_err_t err;
+
+      /* RAID 1 and single-disk RAID 0 don't use a chunksize but code
+         assumes one so set one. */
+      for (i = 0; i < lv->segment_count; i++)
+	{
+	  if (lv->segments[i].type == 1)
+	    lv->segments[i].stripe_size = 64;
+	  if (lv->segments[i].type == GRUB_DISKFILTER_STRIPED
+	      && lv->segments[i].node_count == 1
+	      && lv->segments[i].stripe_size == 0)
+	    lv->segments[i].stripe_size = 64;
+	}
+
+      err = validate_lv(lv);
+      if (err)
+	return err;
       lv->number = lv_num++;
 
       if (lv->fullname)
@@ -888,12 +998,6 @@ grub_diskfilter_vg_register (struct grub_diskfilter_vg *vg)
 	      lv->fullname = tmp;
 	    }
 	}
-      /* RAID 1 doesn't use a chunksize but code assumes one so set
-	 one. */
-      for (i = 0; i < lv->segment_count; i++)
-	if (lv->segments[i].type == 1)
-	  lv->segments[i].stripe_size = 64;
-      lv->vg = vg;
     }
   /* Add our new array to the list.  */
   vg->next = array_list;
@@ -926,6 +1030,11 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
 	n = layout & 0xFF;
 	if (n == 1)
 	  n = (layout >> 8) & 0xFF;
+	if (n == 0)
+	  {
+	    grub_free (uuid);
+	    return NULL;
+	  }
 
 	totsize = grub_divmod64 (nmemb * disk_size, n, 0);
       }
@@ -939,6 +1048,7 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
       break;
 
     default:
+      grub_free (uuid);
       return NULL;
     }
 
@@ -952,7 +1062,7 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
 	    array->lvs->segments->extent_count = totsize;
 	}
 
-      if (array->lvs->segments
+      if (array->lvs && array->lvs->segments
 	  && array->lvs->segments->raid_member_size > disk_size)
 	array->lvs->segments->raid_member_size = disk_size;
 
@@ -961,7 +1071,10 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
     }
   array = grub_zalloc (sizeof (*array));
   if (!array)
-    return NULL;
+    {
+      grub_free (uuid);
+      return NULL;
+    }
   array->uuid = uuid;
   array->uuid_len = uuidlen;
   if (name)
@@ -983,8 +1096,16 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
     goto fail;
   array->lvs->segment_count = 1;
   array->lvs->visible = 1;
-  array->lvs->name = array->name;
-  array->lvs->fullname = array->name;
+  if (array->name)
+    {
+      array->lvs->name = grub_strdup (array->name);
+      if (!array->lvs->name)
+	goto fail;
+      array->lvs->fullname = grub_strdup (array->name);
+      if (!array->lvs->fullname)
+	goto fail;
+    }
+  array->lvs->vg = array;
 
   array->lvs->idname = grub_malloc (sizeof ("mduuid/") + 2 * uuidlen);
   if (!array->lvs->idname)
@@ -1034,13 +1155,26 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
   return array;
 
  fail:
-  grub_free (array->lvs);
+  if (array->lvs)
+    {
+      grub_free (array->lvs->name);
+      grub_free (array->lvs->fullname);
+      grub_free (array->lvs->idname);
+      if (array->lvs->segments)
+	{
+	  grub_free (array->lvs->segments->nodes);
+	  grub_free (array->lvs->segments);
+	}
+      grub_free (array->lvs);
+    }
   while (array->pvs)
     {
       pv = array->pvs->next;
       grub_free (array->pvs);
       array->pvs = pv;
     }
+  grub_free (array->name);
+  grub_free (array->uuid);
   grub_free (array);
   return NULL;
 }
@@ -1143,10 +1277,9 @@ free_array (void)
 	{
 	  unsigned i;
 	  vg->lvs = lv->next;
-	  if (lv->name != lv->fullname)
-	    grub_free (lv->fullname);
-	  if (lv->name != vg->name)
-	    grub_free (lv->name);
+	  grub_free (lv->fullname);
+	  grub_free (lv->name);
+	  grub_free (lv->idname);
 	  for (i = 0; i < lv->segment_count; i++)
 	    grub_free (lv->segments[i].nodes);
 	  grub_free (lv->segments);
diff --git a/grub-core/disk/dmraid_nvidia.c b/grub-core/disk/dmraid_nvidia.c
index 6e6405529..881508cf2 100644
--- a/grub-core/disk/dmraid_nvidia.c
+++ b/grub-core/disk/dmraid_nvidia.c
@@ -99,6 +99,8 @@ grub_dmraid_nv_detect (grub_disk_t disk,
   struct grub_nv_super sb;
   int level;
   grub_uint64_t disk_size;
+  grub_uint32_t capacity;
+  grub_uint8_t total_volumes;
   char *uuid;
 
   if (disk->partition)
@@ -124,11 +126,17 @@ grub_dmraid_nv_detect (grub_disk_t disk,
       return NULL;
     }
 
+  capacity = grub_le_to_cpu32 (sb.capacity);
+  total_volumes = sb.array.total_volumes;
+
   switch (sb.array.raid_level)
     {
     case NV_LEVEL_0:
       level = 0;
-      disk_size = sb.capacity / sb.array.total_volumes;
+      if (total_volumes == 0)
+	/* Not RAID.  */
+	return NULL;
+      disk_size = capacity / total_volumes;
       break;
 
     case NV_LEVEL_1:
@@ -138,7 +146,10 @@ grub_dmraid_nv_detect (grub_disk_t disk,
 
     case NV_LEVEL_5:
       level = 5;
-      disk_size = sb.capacity / (sb.array.total_volumes - 1);
+      if (total_volumes == 0 || total_volumes == 1)
+	/* Not RAID.  */
+	return NULL;
+      disk_size = capacity / (total_volumes - 1);
       break;
 
     default:
diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c
index 3b12c3499..60a6d3c50 100644
--- a/grub-core/disk/efi/efidisk.c
+++ b/grub-core/disk/efi/efidisk.c
@@ -803,7 +803,6 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
       && (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE
 	  || GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE))
     {
-      int is_cdrom = 0;
       struct grub_efidisk_get_device_name_ctx ctx;
       char *dev_name;
       grub_efi_device_path_t *dup_dp;
@@ -824,9 +823,6 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
 		    || GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE)))
 	    break;
 
-	  if (GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE)
-	    is_cdrom = 1;
-
 	  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);
@@ -861,10 +857,13 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
 
 	  if (! ctx.partition_name)
 	    {
+	      /* No partition found. In most cases partition is embed in
+		 the root path anyway, so this is not critical.
+		 This happens only if partition is on partmap that GRUB
+		 doesn't need to access root.
+	       */
 	      grub_disk_close (parent);
-	      if (is_cdrom)
-		return grub_strdup (device_name);
-	      return 0;
+	      return grub_strdup (device_name);
 	    }
 
 	  dev_name = grub_xasprintf ("%s,%s", parent->name,
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
index 9025c9d46..e9d23299a 100644
--- a/grub-core/disk/geli.c
+++ b/grub-core/disk/geli.c
@@ -212,7 +212,8 @@ grub_util_get_geli_uuid (const char *dev)
 
   s = grub_util_get_fd_size (fd, dev, &log_secsize);
   s >>= log_secsize;
-  grub_util_fd_seek (fd, (s << log_secsize) - 512);
+  if (grub_util_fd_seek (fd, (s << log_secsize) - 512) < 0)
+    grub_util_error ("%s", _("couldn't read ELI metadata"));
 
   uuid = xmalloc (GRUB_MD_SHA256->mdlen * 2 + 1);
   if (grub_util_fd_read (fd, (void *) &hdr, 512) < 0)
@@ -225,13 +226,16 @@ grub_util_get_geli_uuid (const char *dev)
 
   /* Look for GELI magic sequence.  */
   if (grub_memcmp (header->magic, GELI_MAGIC, sizeof (GELI_MAGIC))
-      || grub_le_to_cpu32 (header->version) > 5
+      || grub_le_to_cpu32 (header->version) > 7
       || grub_le_to_cpu32 (header->version) < 1)
     grub_util_error ("%s", _("wrong ELI magic or version"));
 
   err = make_uuid ((void *) &hdr, uuid);
   if (err)
-    return NULL;
+    {
+      grub_free (uuid);
+      return NULL;
+    }
 
   return uuid;
 }
@@ -265,7 +269,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
 
   /* Look for GELI magic sequence.  */
   if (grub_memcmp (header.magic, GELI_MAGIC, sizeof (GELI_MAGIC))
-      || grub_le_to_cpu32 (header.version) > 5
+      || grub_le_to_cpu32 (header.version) > 7
       || grub_le_to_cpu32 (header.version) < 1)
     {
       grub_dprintf ("geli", "wrong magic %02x\n", header.magic[0]);
@@ -332,19 +336,29 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
     {
       secondary_cipher = grub_crypto_cipher_open (ciph);
       if (!secondary_cipher)
-	return NULL;
+	{
+	  grub_crypto_cipher_close (cipher);
+	  return NULL;
+	}
+
     }
 
   if (grub_le_to_cpu16 (header.keylen) > 1024)
     {
       grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid keysize %d",
 		  grub_le_to_cpu16 (header.keylen));
+      grub_crypto_cipher_close (cipher);
+      grub_crypto_cipher_close (secondary_cipher);
       return NULL;
     }
 
   newdev = grub_zalloc (sizeof (struct grub_cryptodisk));
   if (!newdev)
-    return NULL;
+    {
+      grub_crypto_cipher_close (cipher);
+      grub_crypto_cipher_close (secondary_cipher);
+      return NULL;
+    }
   newdev->cipher = cipher;
   newdev->secondary_cipher = secondary_cipher;
   newdev->offset = 0;
@@ -391,6 +405,7 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev)
   grub_uint8_t geomkey[GRUB_CRYPTO_MAX_MDLEN];
   grub_uint8_t verify_key[GRUB_CRYPTO_MAX_MDLEN];
   grub_uint8_t zero[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE];
+  grub_uint8_t geli_cipher_key[64];
   char passphrase[MAX_PASSPHRASE] = "";
   unsigned i;
   gcry_err_code_t gcry_err;
@@ -514,6 +529,19 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev)
 	continue;
       grub_printf_ (N_("Slot %d opened\n"), i);
 
+      if (grub_le_to_cpu32 (header.version) >= 7)
+        {
+          /* GELI >=7 uses the cipher_key */
+	  grub_memcpy (geli_cipher_key, candidate_key.cipher_key,
+		sizeof (candidate_key.cipher_key));
+        }
+      else
+        {
+          /* GELI <=6 uses the iv_key */
+	  grub_memcpy (geli_cipher_key, candidate_key.iv_key,
+		sizeof (candidate_key.iv_key));
+        }
+
       /* Set the master key.  */
       if (!dev->rekey)
 	{
@@ -530,13 +558,13 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev)
 	  grub_size_t real_keysize = keysize;
 	  if (grub_le_to_cpu16 (header.alg) == 0x16)
 	    real_keysize *= 2;
-	  /* For a reason I don't know, the IV key is used in rekeying.  */
-	  grub_memcpy (dev->rekey_key, candidate_key.iv_key,
-		       sizeof (candidate_key.iv_key));
+
+	  grub_memcpy (dev->rekey_key, geli_cipher_key,
+		       sizeof (geli_cipher_key));
 	  dev->rekey_derived_size = real_keysize;
 	  dev->last_rekey = -1;
 	  COMPILE_TIME_ASSERT (sizeof (dev->rekey_key)
-			       >= sizeof (candidate_key.iv_key));
+		       >= sizeof (geli_cipher_key));
 	}
 
       dev->iv_prefix_len = sizeof (candidate_key.iv_key);
diff --git a/grub-core/disk/i386/pc/biosdisk.c b/grub-core/disk/i386/pc/biosdisk.c
index 6b2152591..f0aadd111 100644
--- a/grub-core/disk/i386/pc/biosdisk.c
+++ b/grub-core/disk/i386/pc/biosdisk.c
@@ -382,7 +382,8 @@ grub_biosdisk_open (const char *name, grub_disk_t disk)
                 /* Some buggy BIOSes doesn't return the total sectors
                    correctly but returns zero. So if it is zero, compute
                    it by C/H/S returned by the LBA BIOS call.  */
-                total_sectors = drp->cylinders * drp->heads * drp->sectors;
+                total_sectors = ((grub_uint64_t) drp->cylinders)
+		  * drp->heads * drp->sectors;
 	      if (drp->bytes_per_sector
 		  && !(drp->bytes_per_sector & (drp->bytes_per_sector - 1))
 		  && drp->bytes_per_sector >= 512
@@ -419,8 +420,14 @@ grub_biosdisk_open (const char *name, grub_disk_t disk)
 	    }
         }
 
+      if (data->sectors == 0)
+	data->sectors = 63;
+      if (data->heads == 0)
+	data->heads = 255;
+
       if (! total_sectors)
-        total_sectors = data->cylinders * data->heads * data->sectors;
+        total_sectors = ((grub_uint64_t) data->cylinders)
+	  * data->heads * data->sectors;
     }
 
   disk->total_sectors = total_sectors;
diff --git a/grub-core/disk/ieee1275/nand.c b/grub-core/disk/ieee1275/nand.c
index 576e9ccc4..feffa8c4c 100644
--- a/grub-core/disk/ieee1275/nand.c
+++ b/grub-core/disk/ieee1275/nand.c
@@ -113,6 +113,11 @@ grub_nand_open (const char *name, grub_disk_t disk)
     }
 
   data->block_size = (args.size1 >> GRUB_DISK_SECTOR_BITS);
+  if (!data->block_size)
+    {
+      grub_error (GRUB_ERR_UNKNOWN_DEVICE, "invalid block size");
+      goto fail;
+    }
 
   INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 3);
   args.method = (grub_ieee1275_cell_t) "size";
diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c
index 6870b3958..331769b12 100644
--- a/grub-core/disk/ieee1275/ofdisk.c
+++ b/grub-core/disk/ieee1275/ofdisk.c
@@ -34,7 +34,8 @@ struct ofdisk_hash_ent
   char *open_path;
   char *grub_devpath;
   int is_boot;
-  int is_cdrom;
+  int is_removable;
+  int block_size_fails;
   /* Pointer to shortest available name on nodes representing canonical names,
      otherwise NULL.  */
   const char *shortest;
@@ -42,6 +43,10 @@ struct ofdisk_hash_ent
   struct ofdisk_hash_ent *next;
 };
 
+static grub_err_t
+grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size,
+			    struct ofdisk_hash_ent *op);
+
 #define OFDISK_HASH_SZ	8
 static struct ofdisk_hash_ent *ofdisk_hash[OFDISK_HASH_SZ];
 
@@ -123,7 +128,7 @@ ofdisk_hash_add_real (char *devpath)
 }
 
 static int
-check_string_cdrom (const char *str)
+check_string_removable (const char *str)
 {
   const char *ptr = grub_strrchr (str, '/');
 
@@ -131,7 +136,7 @@ check_string_cdrom (const char *str)
     ptr++;
   else
     ptr = str;
-  return (grub_strncmp (ptr, "cdrom", 5) == 0);
+  return (grub_strncmp (ptr, "cdrom", 5) == 0 || grub_strncmp (ptr, "fd", 2) == 0);
 }
 
 static struct ofdisk_hash_ent *
@@ -147,8 +152,8 @@ ofdisk_hash_add (char *devpath, char *curcan)
     {
       p->shortest = p->devpath;
       p->grub_shortest = p->grub_devpath;
-      if (check_string_cdrom (devpath))
-	p->is_cdrom = 1;  
+      if (check_string_removable (devpath))
+	p->is_removable = 1;
       return p;
     }
 
@@ -158,8 +163,8 @@ ofdisk_hash_add (char *devpath, char *curcan)
   else
     grub_free (curcan);
 
-  if (check_string_cdrom (devpath) || check_string_cdrom (curcan))
-    pcan->is_cdrom = 1;
+  if (check_string_removable (devpath) || check_string_removable (curcan))
+    pcan->is_removable = 1;
 
   if (!pcan)
     grub_errno = GRUB_ERR_NONE;
@@ -330,7 +335,7 @@ grub_ofdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
 		}
 	    }
 
-	  if (!ent->is_boot && ent->is_cdrom)
+	  if (!ent->is_boot && ent->is_removable)
 	    continue;
 
 	  if (hook (ent->grub_shortest, hook_data))
@@ -375,6 +380,8 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
   /* XXX: This should be large enough for any possible case.  */
   char prop[64];
   grub_ssize_t actual;
+  grub_uint32_t block_size = 0;
+  grub_err_t err;
 
   if (grub_strncmp (name, "ieee1275/", sizeof ("ieee1275/") - 1) != 0)
       return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
@@ -405,14 +412,6 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
       return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a block device");
     }
 
-  grub_uint32_t block_size = 0;
-  if (grub_ofdisk_get_block_size (devpath, &block_size) == 0)
-    {
-      for (disk->log_sector_size = 0;
-           (1U << disk->log_sector_size) < block_size;
-           disk->log_sector_size++);
-    }
-
   /* XXX: There is no property to read the number of blocks.  There
      should be a property `#blocks', but it is not there.  Perhaps it
      is possible to use seek for this.  */
@@ -429,6 +428,18 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
       return grub_errno;
     disk->id = (unsigned long) op;
     disk->data = op->open_path;
+
+    err = grub_ofdisk_get_block_size (devpath, &block_size, op);
+    if (err)
+      return err;
+    if (block_size != 0)
+      {
+	for (disk->log_sector_size = 0;
+	     (1U << disk->log_sector_size) < block_size;
+	     disk->log_sector_size++);
+      }
+    else
+      disk->log_sector_size = 9;
   }
 
   return 0;
@@ -589,8 +600,9 @@ grub_ofdisk_init (void)
   grub_disk_dev_register (&grub_ofdisk_dev);
 }
 
-grub_err_t
-grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size)
+static grub_err_t
+grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size,
+			    struct ofdisk_hash_ent *op)
 {
   struct size_args_ieee1275
     {
@@ -612,20 +624,34 @@ grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size)
   if (! last_ihandle)
     return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
 
+  *block_size = 0;
+
+  if (op->block_size_fails >= 2)
+    return GRUB_ERR_NONE;
+
   INIT_IEEE1275_COMMON (&args_ieee1275.common, "call-method", 2, 2);
   args_ieee1275.method = (grub_ieee1275_cell_t) "block-size";
   args_ieee1275.ihandle = last_ihandle;
   args_ieee1275.result = 1;
 
-  *block_size = GRUB_DISK_SECTOR_SIZE;
-
-  if ((IEEE1275_CALL_ENTRY_FN (&args_ieee1275) == -1) || (args_ieee1275.result))
-    grub_dprintf ("disk", "can't get block size\n");
-  else
-    if (args_ieee1275.size1
-        && !(args_ieee1275.size1 & (args_ieee1275.size1 - 1))
-        && args_ieee1275.size1 >= 512 && args_ieee1275.size1 <= 16384)
+  if (IEEE1275_CALL_ENTRY_FN (&args_ieee1275) == -1)
+    {
+      grub_dprintf ("disk", "can't get block size: failed call-method\n");
+      op->block_size_fails++;
+    }
+  else if (args_ieee1275.result)
+    {
+      grub_dprintf ("disk", "can't get block size: %lld\n",
+		    (long long) args_ieee1275.result);
+      op->block_size_fails++;
+    }
+  else if (args_ieee1275.size1
+	   && !(args_ieee1275.size1 & (args_ieee1275.size1 - 1))
+	   && args_ieee1275.size1 >= 512 && args_ieee1275.size1 <= 16384)
+    {
+      op->block_size_fails = 0;
       *block_size = args_ieee1275.size1;
+    }
 
   return 0;
 }
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 250202947..86c50c612 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -143,6 +143,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
     {
       grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid keysize %d",
 		  grub_be_to_cpu32 (header.keyBytes));
+      grub_crypto_cipher_close (cipher);
       return NULL;
     }
 
@@ -181,9 +182,10 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
 	}
       if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
 	{
-	  grub_crypto_cipher_close (cipher);
 	  grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d",
 		      cipher->cipher->blocksize);
+	  grub_crypto_cipher_close (cipher);
+	  grub_crypto_cipher_close (secondary_cipher);
 	  return NULL;
 	}
       if (secondary_cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
@@ -191,6 +193,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
 	  grub_crypto_cipher_close (cipher);
 	  grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d",
 		      secondary_cipher->cipher->blocksize);
+	  grub_crypto_cipher_close (secondary_cipher);
 	  return NULL;
 	}
     }
@@ -200,9 +203,9 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
       cipheriv = ciphermode + sizeof ("lrw-") - 1;
       if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
 	{
-	  grub_crypto_cipher_close (cipher);
 	  grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported LRW block size: %d",
 		      cipher->cipher->blocksize);
+	  grub_crypto_cipher_close (cipher);
 	  return NULL;
 	}
     }
@@ -225,6 +228,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
 	  || cipher->cipher->blocksize == 0)
 	grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported benbi blocksize: %d",
 		    cipher->cipher->blocksize);
+	/* FIXME should we return an error here? */
       for (benbi_log = 0; 
 	   (cipher->cipher->blocksize << benbi_log) < GRUB_DISK_SECTOR_SIZE;
 	   benbi_log++);
@@ -243,6 +247,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
       if (!essiv_hash)
 	{
 	  grub_crypto_cipher_close (cipher);
+	  grub_crypto_cipher_close (secondary_cipher);
 	  grub_error (GRUB_ERR_FILE_NOT_FOUND,
 		      "Couldn't load %s hash", hash_str);
 	  return NULL;
@@ -251,12 +256,14 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
       if (!essiv_cipher)
 	{
 	  grub_crypto_cipher_close (cipher);
+	  grub_crypto_cipher_close (secondary_cipher);
 	  return NULL;
 	}
     }
   else
     {
       grub_crypto_cipher_close (cipher);
+      grub_crypto_cipher_close (secondary_cipher);
       grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown IV mode: %s",
 		  cipheriv);
       return NULL;
@@ -276,7 +283,12 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
 
   newdev = grub_zalloc (sizeof (struct grub_cryptodisk));
   if (!newdev)
-    return NULL;
+    {
+      grub_crypto_cipher_close (cipher);
+      grub_crypto_cipher_close (essiv_cipher);
+      grub_crypto_cipher_close (secondary_cipher);
+      return NULL;
+    }
   newdev->cipher = cipher;
   newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
   newdev->source_disk = NULL;
@@ -451,6 +463,7 @@ luks_recover_key (grub_disk_t source,
       return GRUB_ERR_NONE;
     }
 
+  grub_free (split_key);
   return GRUB_ACCESS_DENIED;
 }
 
diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c
index 862a9664f..9b97004d8 100644
--- a/grub-core/disk/lvm.c
+++ b/grub-core/disk/lvm.c
@@ -426,7 +426,7 @@ grub_lvm_detect (grub_disk_t disk,
 #endif
 		  goto lvs_fail;
 		}
-	      lv->segments = grub_malloc (sizeof (*seg) * lv->segment_count);
+	      lv->segments = grub_zalloc (sizeof (*seg) * lv->segment_count);
 	      seg = lv->segments;
 
 	      for (i = 0; i < lv->segment_count; i++)
@@ -577,13 +577,17 @@ grub_lvm_detect (grub_disk_t disk,
 		      if (is_pvmove)
 			seg->node_count = 1;
 		    }
-		  else if (grub_memcmp (p, "raid", sizeof ("raid") - 1)
-			   == 0 && (p[sizeof ("raid") - 1] >= '4'
-				    && p[sizeof ("raid") - 1] <= '6')
+		  else if (grub_memcmp (p, "raid", sizeof ("raid") - 1) == 0
+			   && ((p[sizeof ("raid") - 1] >= '4'
+				&& p[sizeof ("raid") - 1] <= '6')
+			       || p[sizeof ("raid") - 1] == '1')
 			   && p[sizeof ("raidX") - 1] == '"')
 		    {
 		      switch (p[sizeof ("raid") - 1])
 			{
+			case '1':
+			  seg->type = GRUB_DISKFILTER_MIRROR;
+			  break;
 			case '4':
 			  seg->type = GRUB_DISKFILTER_RAID4;
 			  seg->layout = GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC;
@@ -608,16 +612,18 @@ grub_lvm_detect (grub_disk_t disk,
 			  goto lvs_segment_fail;
 			}
 
-		      seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = ");
-		      if (p == NULL)
+		      if (seg->type != GRUB_DISKFILTER_MIRROR)
 			{
+			  seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = ");
+			  if (p == NULL)
+			    {
 #ifdef GRUB_UTIL
-			  grub_util_info ("unknown stripe_size\n");
+			      grub_util_info ("unknown stripe_size\n");
 #endif
-			  goto lvs_segment_fail;
+			      goto lvs_segment_fail;
+			    }
 			}
 
-
 		      seg->nodes = grub_zalloc (sizeof (seg->nodes[0])
 						* seg->node_count);
 
@@ -625,7 +631,7 @@ grub_lvm_detect (grub_disk_t disk,
 		      if (p == NULL)
 			{
 #ifdef GRUB_UTIL
-			  grub_util_info ("unknown mirrors\n");
+			  grub_util_info ("unknown raids\n");
 #endif
 			  goto lvs_segment_fail2;
 			}
diff --git a/grub-core/disk/raid6_recover.c b/grub-core/disk/raid6_recover.c
index f9ec632fb..aa674f6ca 100644
--- a/grub-core/disk/raid6_recover.c
+++ b/grub-core/disk/raid6_recover.c
@@ -63,6 +63,16 @@ grub_raid6_init_table (void)
     }
 }
 
+static unsigned
+mod_255 (unsigned x)
+{
+  while (x > 0xff)
+    x = (x >> 8) + (x & 0xff);
+  if (x == 0xff)
+    return 0;
+  return x;
+}
+
 static grub_err_t
 grub_raid6_recover (struct grub_diskfilter_segment *array, int disknr, int p,
                     char *buf, grub_disk_addr_t sector, grub_size_t size)
@@ -162,11 +172,11 @@ grub_raid6_recover (struct grub_diskfilter_segment *array, int disknr, int p,
 
       grub_crypto_xor (qbuf, qbuf, buf, size);
 
-      c = ((255 ^ bad1)
-	   + (255 ^ powx_inv[(powx[bad2 + (bad1 ^ 255)] ^ 1)])) % 255;
+      c = mod_255((255 ^ bad1)
+		  + (255 ^ powx_inv[(powx[bad2 + (bad1 ^ 255)] ^ 1)]));
       grub_raid_block_mulx (c, qbuf, size);
 
-      c = ((unsigned) bad2 + c) % 255;
+      c = mod_255((unsigned) bad2 + c);
       grub_raid_block_mulx (c, pbuf, size);
 
       grub_crypto_xor (pbuf, pbuf, qbuf, size);
diff --git a/grub-core/disk/xen/xendisk.c b/grub-core/disk/xen/xendisk.c
index 2b11c2a2e..b18a9238d 100644
--- a/grub-core/disk/xen/xendisk.c
+++ b/grub-core/disk/xen/xendisk.c
@@ -40,6 +40,7 @@ struct virtdisk
   grub_xen_evtchn_t evtchn;
   void *dma_page;
   grub_xen_grant_t dma_grant;
+  struct virtdisk *compat_next;
 };
 
 #define xen_wmb() mb()
@@ -47,6 +48,7 @@ struct virtdisk
 
 static struct virtdisk *virtdisks;
 static grub_size_t vdiskcnt;
+struct virtdisk *compat_head;
 
 static int
 grub_virtdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
@@ -66,20 +68,32 @@ grub_virtdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
 static grub_err_t
 grub_virtdisk_open (const char *name, grub_disk_t disk)
 {
-  grub_size_t i;
+  int i;
   grub_uint32_t secsize;
   char fdir[200];
   char *buf;
+  int num = -1;
+  struct virtdisk *vd;
 
-  for (i = 0; i < vdiskcnt; i++)
-    if (grub_strcmp (name, virtdisks[i].fullname) == 0)
+  /* For compatibility with pv-grub legacy menu.lst accept hdX as disk name */
+  if (name[0] == 'h' && name[1] == 'd' && name[2])
+    {
+      num = grub_strtoul (name + 2, 0, 10);
+      if (grub_errno)
+	{
+	  grub_errno = 0;
+	  num = -1;
+	}
+    }
+  for (i = 0, vd = compat_head; vd; vd = vd->compat_next, i++)
+    if (i == num || grub_strcmp (name, vd->fullname) == 0)
       break;
-  if (i == vdiskcnt)
+  if (!vd)
     return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a virtdisk");
-  disk->data = &virtdisks[i];
-  disk->id = i;
+  disk->data = vd;
+  disk->id = vd - virtdisks;
 
-  grub_snprintf (fdir, sizeof (fdir), "%s/sectors", virtdisks[i].backend_dir);
+  grub_snprintf (fdir, sizeof (fdir), "%s/sectors", vd->backend_dir);
   buf = grub_xenstore_get_file (fdir, NULL);
   if (!buf)
     return grub_errno;
@@ -87,8 +101,7 @@ grub_virtdisk_open (const char *name, grub_disk_t disk)
   if (grub_errno)
     return grub_errno;
 
-  grub_snprintf (fdir, sizeof (fdir), "%s/sector-size",
-		 virtdisks[i].backend_dir);
+  grub_snprintf (fdir, sizeof (fdir), "%s/sector-size", vd->backend_dir);
   buf = grub_xenstore_get_file (fdir, NULL);
   if (!buf)
     return grub_errno;
@@ -264,6 +277,7 @@ fill (const char *dir, void *data)
   grub_err_t err;
   void *buf;
   struct evtchn_alloc_unbound alloc_unbound;
+  struct virtdisk **prev = &compat_head, *vd = compat_head;
 
   /* Shouldn't happen unles some hotplug happened.  */
   if (vdiskcnt >= *ctr)
@@ -374,6 +388,19 @@ fill (const char *dir, void *data)
 
   virtdisks[vdiskcnt].frontend_dir = grub_strdup (fdir);
 
+  /* For compatibility with pv-grub maintain linked list sorted by handle
+     value in increasing order. This allows mapping of (hdX) disk names
+     from legacy menu.lst */
+  while (vd)
+    {
+      if (vd->handle > virtdisks[vdiskcnt].handle)
+	break;
+      prev = &vd->compat_next;
+      vd = vd->compat_next;
+    }
+  virtdisks[vdiskcnt].compat_next = vd;
+  *prev = &virtdisks[vdiskcnt];
+
   vdiskcnt++;
   return 0;
 
diff --git a/grub-core/font/font.c b/grub-core/font/font.c
index 14b93e172..53d76a64d 100644
--- a/grub-core/font/font.c
+++ b/grub-core/font/font.c
@@ -777,6 +777,7 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code)
 	  if (grub_file_read (font->file, glyph->bitmap, len) != len)
 	    {
 	      remove_font (font);
+	      grub_free (glyph);
 	      return 0;
 	    }
 	}
@@ -1285,7 +1286,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id,
 	    - grub_font_get_xheight (combining_glyphs[i]->font) - 1;
 	  if (space <= 0)
 	    space = 1 + (grub_font_get_xheight (main_glyph->font)) / 8;
-
+	  /* Fallthrough.  */
 	case GRUB_UNICODE_STACK_ATTACHED_ABOVE:
 	  do_blit (combining_glyphs[i], targetx,
 		   -(ctx.bounds.height + ctx.bounds.y + space
@@ -1326,6 +1327,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id,
 		    + combining_glyphs[i]->height);
 	  if (space <= 0)
 	    space = 1 + (grub_font_get_xheight (main_glyph->font)) / 8;
+	  /* Fallthrough.  */
 
 	case GRUB_UNICODE_STACK_ATTACHED_BELOW:
 	  do_blit (combining_glyphs[i], targetx, -(ctx.bounds.y - space),
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
index 95a8fa6b3..9cffa91fa 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -680,6 +680,8 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
 	grub_uint64_t stripen;
 	grub_uint64_t stripe_offset;
 	grub_uint64_t off = addr - grub_le_to_cpu64 (key->offset);
+	grub_uint64_t chunk_stripe_length;
+	grub_uint16_t nstripes;
 	unsigned redundancy = 1;
 	unsigned i, j;
 
@@ -690,15 +692,17 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
 			       "couldn't find the chunk descriptor");
 	  }
 
+	nstripes = grub_le_to_cpu16 (chunk->nstripes) ? : 1;
+	chunk_stripe_length = grub_le_to_cpu64 (chunk->stripe_length) ? : 512;
 	grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T
 		      "+0x%" PRIxGRUB_UINT64_T
 		      " (%d stripes (%d substripes) of %"
 		      PRIxGRUB_UINT64_T ")\n",
 		      grub_le_to_cpu64 (key->offset),
 		      grub_le_to_cpu64 (chunk->size),
-		      grub_le_to_cpu16 (chunk->nstripes),
+		      nstripes,
 		      grub_le_to_cpu16 (chunk->nsubstripes),
-		      grub_le_to_cpu64 (chunk->stripe_length));
+		      chunk_stripe_length);
 
 	switch (grub_le_to_cpu64 (chunk->type)
 		& ~GRUB_BTRFS_CHUNK_TYPE_BITS_DONTCARE)
@@ -708,8 +712,10 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
 	      grub_uint64_t stripe_length;
 	      grub_dprintf ("btrfs", "single\n");
 	      stripe_length = grub_divmod64 (grub_le_to_cpu64 (chunk->size),
-					     grub_le_to_cpu16 (chunk->nstripes),
+					     nstripes,
 					     NULL);
+	      if (stripe_length == 0)
+		stripe_length = 512;
 	      stripen = grub_divmod64 (off, stripe_length, &stripe_offset);
 	      csize = (stripen + 1) * stripe_length - off;
 	      break;
@@ -730,33 +736,34 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
 	      grub_uint64_t low;
 	      grub_dprintf ("btrfs", "RAID0\n");
 	      middle = grub_divmod64 (off,
-				      grub_le_to_cpu64 (chunk->stripe_length),
+				      chunk_stripe_length,
 				      &low);
 
-	      high = grub_divmod64 (middle, grub_le_to_cpu16 (chunk->nstripes),
+	      high = grub_divmod64 (middle, nstripes,
 				    &stripen);
 	      stripe_offset =
-		low + grub_le_to_cpu64 (chunk->stripe_length) * high;
-	      csize = grub_le_to_cpu64 (chunk->stripe_length) - low;
+		low + chunk_stripe_length * high;
+	      csize = chunk_stripe_length - low;
 	      break;
 	    }
 	  case GRUB_BTRFS_CHUNK_TYPE_RAID10:
 	    {
 	      grub_uint64_t middle, high;
 	      grub_uint64_t low;
+	      grub_uint16_t nsubstripes;
+	      nsubstripes = grub_le_to_cpu16 (chunk->nsubstripes) ? : 1;
 	      middle = grub_divmod64 (off,
-				      grub_le_to_cpu64 (chunk->stripe_length),
+				      chunk_stripe_length,
 				      &low);
 
 	      high = grub_divmod64 (middle,
-				    grub_le_to_cpu16 (chunk->nstripes)
-				    / grub_le_to_cpu16 (chunk->nsubstripes),
+				    nstripes / nsubstripes ? : 1,
 				    &stripen);
-	      stripen *= grub_le_to_cpu16 (chunk->nsubstripes);
-	      redundancy = grub_le_to_cpu16 (chunk->nsubstripes);
-	      stripe_offset = low + grub_le_to_cpu64 (chunk->stripe_length)
+	      stripen *= nsubstripes;
+	      redundancy = nsubstripes;
+	      stripe_offset = low + chunk_stripe_length
 		* high;
-	      csize = grub_le_to_cpu64 (chunk->stripe_length) - low;
+	      csize = chunk_stripe_length - low;
 	      break;
 	    }
 	  default:
diff --git a/grub-core/fs/cbfs.c b/grub-core/fs/cbfs.c
index 35750a0e4..a34eb88cb 100644
--- a/grub-core/fs/cbfs.c
+++ b/grub-core/fs/cbfs.c
@@ -74,8 +74,7 @@ grub_cbfs_find_file (struct grub_archelp_data *data, char **name,
       (void) mtime;
       offset = grub_be_to_cpu32 (hd.offset);
 
-      if (mode)
-	*mode = GRUB_ARCHELP_ATTR_FILE | GRUB_ARCHELP_ATTR_NOTIME;
+      *mode = GRUB_ARCHELP_ATTR_FILE | GRUB_ARCHELP_ATTR_NOTIME;
 
       namesize = offset;
       if (namesize >= sizeof (hd))
@@ -144,7 +143,7 @@ static struct grub_archelp_data *
 grub_cbfs_mount (grub_disk_t disk)
 {
   struct cbfs_file hd;
-  struct grub_archelp_data *data;
+  struct grub_archelp_data *data = NULL;
   grub_uint32_t ptr;
   grub_off_t header_off;
   struct cbfs_header head;
@@ -196,6 +195,7 @@ grub_cbfs_mount (grub_disk_t disk)
   return data;
 
 fail:
+  grub_free (data);
   grub_error (GRUB_ERR_BAD_FS, "not a cbfs filesystem");
   return 0;
 }
diff --git a/grub-core/fs/cpio_common.c b/grub-core/fs/cpio_common.c
index b0ae9f445..50fea47d1 100644
--- a/grub-core/fs/cpio_common.c
+++ b/grub-core/fs/cpio_common.c
@@ -61,8 +61,15 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
   modeval = read_number (hd.mode, ARRAY_SIZE (hd.mode));
   namesize = read_number (hd.namesize, ARRAY_SIZE (hd.namesize));
 
-  if (mode)
-    *mode = modeval;
+  /* Don't allow negative numbers.  */
+  if (namesize >= 0x80000000)
+    {
+      /* Probably a corruption, don't attempt to recover.  */
+      *mode = GRUB_ARCHELP_ATTR_END;
+      return GRUB_ERR_NONE;
+    }
+
+  *mode = modeval;
 
   *name = grub_malloc (namesize + 1);
   if (*name == NULL)
diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c
index 5f7a2b9d5..5199cb0c1 100644
--- a/grub-core/fs/ext2.c
+++ b/grub-core/fs/ext2.c
@@ -100,6 +100,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
 #define EXT2_FEATURE_INCOMPAT_META_BG		0x0010
 #define EXT4_FEATURE_INCOMPAT_EXTENTS		0x0040 /* Extents used */
 #define EXT4_FEATURE_INCOMPAT_64BIT		0x0080
+#define EXT4_FEATURE_INCOMPAT_MMP		0x0100
 #define EXT4_FEATURE_INCOMPAT_FLEX_BG		0x0200
 
 /* The set of back-incompatible features this driver DOES support. Add (OR)
@@ -107,6 +108,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
 #define EXT2_DRIVER_SUPPORTED_INCOMPAT ( EXT2_FEATURE_INCOMPAT_FILETYPE \
                                        | EXT4_FEATURE_INCOMPAT_EXTENTS  \
                                        | EXT4_FEATURE_INCOMPAT_FLEX_BG \
+                                       | EXT2_FEATURE_INCOMPAT_META_BG \
                                        | EXT4_FEATURE_INCOMPAT_64BIT)
 /* List of rationales for the ignored "incompatible" features:
  * needs_recovery: Not really back-incompatible - was added as such to forbid
@@ -114,8 +116,13 @@ GRUB_MOD_LICENSE ("GPLv3+");
  *                 journal because they will ignore the journal, but the next
  *                 ext3 driver to mount the volume will find the journal and
  *                 replay it, potentially corrupting the metadata written by
- *                 the ext2 drivers. Safe to ignore for this RO driver.  */
-#define EXT2_DRIVER_IGNORED_INCOMPAT ( EXT3_FEATURE_INCOMPAT_RECOVER )
+ *                 the ext2 drivers. Safe to ignore for this RO driver.
+ * mmp:            Not really back-incompatible - was added as such to
+ *                 avoid multiple read-write mounts. Safe to ignore for this
+ *                 RO driver.
+ */
+#define EXT2_DRIVER_IGNORED_INCOMPAT ( EXT3_FEATURE_INCOMPAT_RECOVER \
+				     | EXT4_FEATURE_INCOMPAT_MMP)
 
 
 #define EXT3_JOURNAL_MAGIC_NUMBER	0xc03b3998U
@@ -331,16 +338,68 @@ static grub_dl_t my_mod;
 
 
 
+/* Check is a = b^x for some x.  */
+static inline int
+is_power_of (grub_uint64_t a, grub_uint32_t b)
+{
+  grub_uint64_t c;
+  /* Prevent overflow assuming b < 8.  */
+  if (a >= (1LL << 60))
+    return 0;
+  for (c = 1; c <= a; c *= b);
+  return (c == a);
+}
+
+
+static inline int
+group_has_super_block (struct grub_ext2_data *data, grub_uint64_t group)
+{
+  if (!(data->sblock.feature_ro_compat
+	& grub_cpu_to_le32_compile_time(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)))
+    return 1;
+  /* Algorithm looked up in Linux source.  */
+  if (group <= 1)
+    return 1;
+  /* Even number is never a power of odd number.  */
+  if (!(group & 1))
+    return 0;
+  return (is_power_of(group, 7) || is_power_of(group, 5) ||
+	  is_power_of(group, 3));
+}
+
 /* Read into BLKGRP the blockgroup descriptor of blockgroup GROUP of
    the mounted filesystem DATA.  */
 inline static grub_err_t
-grub_ext2_blockgroup (struct grub_ext2_data *data, int group,
+grub_ext2_blockgroup (struct grub_ext2_data *data, grub_uint64_t group,
 		      struct grub_ext2_block_group *blkgrp)
 {
+  grub_uint64_t full_offset = (group << data->log_group_desc_size);
+  grub_uint64_t block, offset;
+  block = (full_offset >> LOG2_BLOCK_SIZE (data));
+  offset = (full_offset & ((1 << LOG2_BLOCK_SIZE (data)) - 1));
+  if ((data->sblock.feature_incompat
+       & grub_cpu_to_le32_compile_time (EXT2_FEATURE_INCOMPAT_META_BG))
+      && block >= grub_le_to_cpu32(data->sblock.first_meta_bg))
+    {
+      grub_uint64_t first_block_group;
+      /* Find the first block group for which a descriptor
+	 is stored in given block. */
+      first_block_group = (block << (LOG2_BLOCK_SIZE (data)
+				     - data->log_group_desc_size));
+
+      block = (first_block_group
+	       * grub_le_to_cpu32(data->sblock.blocks_per_group));
+
+      if (group_has_super_block (data, first_block_group))
+	block++;
+    }
+  else
+    /* Superblock.  */
+    block++;
   return grub_disk_read (data->disk,
-                         ((grub_le_to_cpu32 (data->sblock.first_data_block) + 1)
-                          << LOG2_EXT2_BLOCK_SIZE (data)),
-			 group << data->log_group_desc_size,
+                         ((grub_le_to_cpu32 (data->sblock.first_data_block)
+			   + block)
+                          << LOG2_EXT2_BLOCK_SIZE (data)), offset,
 			 sizeof (struct grub_ext2_block_group), blkgrp);
 }
 
@@ -484,6 +543,10 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
 
 indirect:
   do {
+    /* If the indirect block is zero, all child blocks are absent
+       (i.e. filled with zeros.) */
+    if (indir == 0)
+      return 0;
     if (grub_disk_read (data->disk,
 			((grub_disk_addr_t) grub_le_to_cpu32 (indir))
 			<< log2_blksz,
@@ -573,7 +636,12 @@ grub_ext2_mount (grub_disk_t disk)
 
   /* Make sure this is an ext2 filesystem.  */
   if (data->sblock.magic != grub_cpu_to_le16_compile_time (EXT2_MAGIC)
-      || grub_le_to_cpu32 (data->sblock.log2_block_size) >= 16)
+      || grub_le_to_cpu32 (data->sblock.log2_block_size) >= 16
+      || data->sblock.inodes_per_group == 0
+      /* 20 already means 1GiB blocks. We don't want to deal with blocks overflowing int32. */
+      || grub_le_to_cpu32 (data->sblock.log2_block_size) > 20
+      || EXT2_INODE_SIZE (data) == 0
+      || EXT2_BLOCK_SIZE (data) / EXT2_INODE_SIZE (data) == 0)
     {
       grub_error (GRUB_ERR_BAD_FS, "not an ext2 filesystem");
       goto fail;
diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c
index 79fe864d7..71537ff44 100644
--- a/grub-core/fs/fat.c
+++ b/grub-core/fs/fat.c
@@ -1136,7 +1136,7 @@ grub_fat_label (grub_device_t device, char **label)
   if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
     {
       grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
-      return 0;
+      goto fail;
     }
 
   err = grub_fat_iterate_init (&ctxt);
diff --git a/grub-core/fs/fshelp.c b/grub-core/fs/fshelp.c
index 42bd542bb..b899bed04 100644
--- a/grub-core/fs/fshelp.c
+++ b/grub-core/fs/fshelp.c
@@ -252,6 +252,13 @@ grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node,
   grub_disk_addr_t i, blockcnt;
   int blocksize = 1 << (log2blocksize + GRUB_DISK_SECTOR_BITS);
 
+  if (pos > filesize)
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE,
+		  N_("attempt to read past the end of file"));
+      return -1;
+    }
+
   /* Adjust LEN so it we can't read past the end of the file.  */
   if (pos + len > filesize)
     len = filesize - pos;
diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c
index d1dc01545..06cf0c7ab 100644
--- a/grub-core/fs/hfs.c
+++ b/grub-core/fs/hfs.c
@@ -330,6 +330,7 @@ grub_hfs_mount (grub_disk_t disk)
 
   /* Check if this is a HFS filesystem.  */
   if (grub_be_to_cpu16 (data->sblock.magic) != GRUB_HFS_MAGIC
+      || data->sblock.blksz == 0
       || (data->sblock.blksz & grub_cpu_to_be32_compile_time (0xc00001ff)))
     {
       grub_error (GRUB_ERR_BAD_FS, "not an HFS filesystem");
@@ -367,6 +368,11 @@ grub_hfs_mount (grub_disk_t disk)
   data->cat_root = grub_be_to_cpu32 (treehead.head.root_node);
   data->cat_size = grub_be_to_cpu16 (treehead.head.node_size);
 
+  if (data->cat_size == 0
+      || data->blksz < data->cat_size
+      || data->blksz < data->ext_size)
+    goto fail;
+
   /* Lookup the root directory node in the catalog tree using the
      volume name.  */
   key.parent_dir = grub_cpu_to_be32_compile_time (1);
@@ -686,6 +692,7 @@ grub_hfs_iterate_records (struct grub_hfs_data *data, int type, int idx,
       int i;
       struct grub_hfs_extent *dat;
       int blk;
+      grub_uint16_t reccnt;
 
       dat = (struct grub_hfs_extent *) (type == 0
 					? (&data->sblock.catalog_recs)
@@ -704,8 +711,12 @@ grub_hfs_iterate_records (struct grub_hfs_data *data, int type, int idx,
 	  return grub_errno;
 	}
 
+      reccnt = grub_be_to_cpu16 (node->node.reccnt);
+      if (reccnt > (nodesize >> 1))
+	reccnt = (nodesize >> 1);
+
       /* Iterate over all records in this node.  */
-      for (i = 0; i < grub_be_to_cpu16 (node->node.reccnt); i++)
+      for (i = 0; i < reccnt; i++)
 	{
 	  int pos = (nodesize >> 1) - 1 - i;
  	  struct pointer
@@ -713,16 +724,19 @@ grub_hfs_iterate_records (struct grub_hfs_data *data, int type, int idx,
 	    grub_uint8_t keylen;
 	    grub_uint8_t key;
 	  } GRUB_PACKED *pnt;
-	  pnt = (struct pointer *) (grub_be_to_cpu16 (node->offsets[pos])
-				    + node->rawnode);
+	  grub_uint16_t off = grub_be_to_cpu16 (node->offsets[pos]);
+	  if (off > nodesize - sizeof(*pnt))
+	    continue;
+	  pnt = (struct pointer *) (off + node->rawnode);
+	  if (nodesize < (grub_size_t) off + pnt->keylen + 1)
+	    continue;
 
 	  struct grub_hfs_record rec =
 	    {
 	      &pnt->key,
 	      pnt->keylen,
 	      &pnt->key + pnt->keylen +(pnt->keylen + 1) % 2,
-	      nodesize - grub_be_to_cpu16 (node->offsets[pos])
-	      - pnt->keylen - 1
+	      nodesize - off - pnt->keylen - 1
 	    };
 
 	  if (node_hook (&node->node, &rec, hook_arg))
@@ -1300,6 +1314,12 @@ grub_hfs_open (struct grub_file *file, const char *name)
 
   data = grub_hfs_mount (file->device->disk);
 
+  if (!data)
+    {
+      grub_dl_unref (my_mod);
+      return grub_errno;
+    }
+
   if (grub_hfs_find_dir (data, name, &frec, 0))
     {
       grub_free (data);
diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c
index 950d8a1e1..21159e858 100644
--- a/grub-core/fs/hfsplus.c
+++ b/grub-core/fs/hfsplus.c
@@ -336,6 +336,9 @@ grub_hfsplus_mount (grub_disk_t disk)
   data->case_sensitive = ((magic == GRUB_HFSPLUSX_MAGIC) &&
 			  (header.key_compare == GRUB_HFSPLUSX_BINARYCOMPARE));
 
+  if (data->catalog_tree.nodesize < 2)
+    goto fail;
+
   if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 0, 0,
 			      sizeof (struct grub_hfsplus_btnode),
 			      sizeof (header), (char *) &header) <= 0)
@@ -350,6 +353,9 @@ grub_hfsplus_mount (grub_disk_t disk)
   data->extoverflow_tree.root = grub_be_to_cpu32 (header.root);
   data->extoverflow_tree.nodesize = grub_be_to_cpu16 (header.nodesize);
 
+  if (data->extoverflow_tree.nodesize < 2)
+    goto fail;
+
   if (grub_hfsplus_read_file (&data->attr_tree.file, 0, 0,
 			      sizeof (struct grub_hfsplus_btnode),
 			      sizeof (header), (char *) &header) <= 0)
@@ -723,7 +729,10 @@ list_nodes (void *record, void *hook_arg)
 
       /* If the name is obviously invalid, skip this node.  */
       if (catkey->name[i] == 0)
-	return 0;
+	{
+	  grub_free (filename);
+	  return 0;
+	}
     }
 
   *grub_utf16_to_utf8 ((grub_uint8_t *) filename, catkey->name,
@@ -745,7 +754,10 @@ list_nodes (void *record, void *hook_arg)
      callback function.  */
   node = grub_malloc (sizeof (*node));
   if (!node)
-    return 1;
+    {
+      grub_free (filename);
+      return 1;
+    }
   node->data = ctx->dir->data;
   node->compressed = 0;
   node->cbuf = 0;
@@ -780,8 +792,8 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
   };
 
   struct grub_hfsplus_key_internal intern;
-  struct grub_hfsplus_btnode *node;
-  grub_disk_addr_t ptr;
+  struct grub_hfsplus_btnode *node = NULL;
+  grub_disk_addr_t ptr = 0;
 
   {
     struct grub_fshelp_node *fsnode;
@@ -964,8 +976,8 @@ grub_hfsplus_label (grub_device_t device, char **label)
   struct grub_hfsplus_catkey *catkey;
   int i, label_len;
   struct grub_hfsplus_key_internal intern;
-  struct grub_hfsplus_btnode *node;
-  grub_disk_addr_t ptr;
+  struct grub_hfsplus_btnode *node = NULL;
+  grub_disk_addr_t ptr = 0;
 
   *label = 0;
 
diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c
index 6a6677337..67a67cf40 100644
--- a/grub-core/fs/iso9660.c
+++ b/grub-core/fs/iso9660.c
@@ -959,14 +959,15 @@ grub_iso9660_read (grub_file_t file, char *buf, grub_size_t len)
 {
   struct grub_iso9660_data *data =
     (struct grub_iso9660_data *) file->data;
+  grub_err_t err;
 
   /* XXX: The file is stored in as a single extent.  */
   data->disk->read_hook = file->read_hook;
   data->disk->read_hook_data = file->read_hook_data;
-  read_node (data->node, file->offset, len, buf);
+  err = read_node (data->node, file->offset, len, buf);
   data->disk->read_hook = NULL;
 
-  if (grub_errno)
+  if (err || grub_errno)
     return -1;
 
   return len;
diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c
index 98e1b71ec..d451b3426 100644
--- a/grub-core/fs/minix.c
+++ b/grub-core/fs/minix.c
@@ -65,7 +65,6 @@ typedef grub_uint16_t grub_minix_uintn_t;
 #define grub_minix_to_cpu_n grub_minix_to_cpu16
 #endif
 
-#define GRUB_MINIX_INODE_BLKSZ(data) sizeof (grub_minix_uintn_t)
 #ifdef MODE_MINIX3
 typedef grub_uint32_t grub_minix_ino_t;
 #define grub_minix_to_cpu_ino grub_minix_to_cpu32
@@ -83,19 +82,6 @@ typedef grub_uint16_t grub_minix_ino_t;
 #define GRUB_MINIX_INODE_DINDIR_ZONE(data) (grub_minix_to_cpu_n \
 					    (data->inode.double_indir_zone))
 
-#ifndef MODE_MINIX3
-#define GRUB_MINIX_LOG2_ZONESZ	(GRUB_MINIX_LOG2_BSIZE				\
-				 + grub_minix_to_cpu16 (data->sblock.log2_zone_size))
-#endif
-#define GRUB_MINIX_ZONESZ	((grub_uint64_t) data->block_size <<			\
-				 (GRUB_DISK_SECTOR_BITS + grub_minix_to_cpu16 (data->sblock.log2_zone_size)))
-
-#ifdef MODE_MINIX3
-#define GRUB_MINIX_ZONE2SECT(zone) ((zone) * data->block_size)
-#else
-#define GRUB_MINIX_ZONE2SECT(zone) ((zone) << GRUB_MINIX_LOG2_ZONESZ)
-#endif
-
 
 #ifdef MODE_MINIX3
 struct grub_minix_sblock
@@ -172,6 +158,7 @@ struct grub_minix_data
 {
   struct grub_minix_sblock sblock;
   struct grub_minix_inode inode;
+  grub_uint32_t block_per_zone;
   grub_minix_ino_t ino;
   int linknest;
   grub_disk_t disk;
@@ -184,15 +171,32 @@ static grub_dl_t my_mod;
 static grub_err_t grub_minix_find_file (struct grub_minix_data *data,
 					const char *path);
 
+#ifdef MODE_MINIX3
+static inline grub_disk_addr_t
+grub_minix_zone2sect (struct grub_minix_data *data, grub_minix_uintn_t zone)
+{
+  return ((grub_disk_addr_t) zone) * data->block_size;
+}
+#else
+static inline grub_disk_addr_t
+grub_minix_zone2sect (struct grub_minix_data *data, grub_minix_uintn_t zone)
+{
+  int log2_zonesz = (GRUB_MINIX_LOG2_BSIZE
+		     + grub_minix_to_cpu16 (data->sblock.log2_zone_size));
+  return (((grub_disk_addr_t) zone) << log2_zonesz);
+}
+#endif
+
+
   /* Read the block pointer in ZONE, on the offset NUM.  */
 static grub_minix_uintn_t
-grub_get_indir (struct grub_minix_data *data, 
+grub_get_indir (struct grub_minix_data *data,
 		 grub_minix_uintn_t zone,
 		 grub_minix_uintn_t num)
 {
   grub_minix_uintn_t indirn;
   grub_disk_read (data->disk,
-		  GRUB_MINIX_ZONE2SECT(zone),
+		  grub_minix_zone2sect(data, zone),
 		  sizeof (grub_minix_uintn_t) * num,
 		  sizeof (grub_minix_uintn_t), (char *) &indirn);
   return grub_minix_to_cpu_n (indirn);
@@ -202,8 +206,6 @@ static grub_minix_uintn_t
 grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk)
 {
   grub_minix_uintn_t indir;
-  const grub_uint32_t block_per_zone = (GRUB_MINIX_ZONESZ
-					/ GRUB_MINIX_INODE_BLKSZ (data));
 
   /* Direct block.  */
   if (blk < GRUB_MINIX_INODE_DIR_BLOCKS)
@@ -211,33 +213,33 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk)
 
   /* Indirect block.  */
   blk -= GRUB_MINIX_INODE_DIR_BLOCKS;
-  if (blk < block_per_zone)
+  if (blk < data->block_per_zone)
     {
       indir = grub_get_indir (data, GRUB_MINIX_INODE_INDIR_ZONE (data), blk);
       return indir;
     }
 
   /* Double indirect block.  */
-  blk -= block_per_zone;
-  if (blk < block_per_zone * block_per_zone)
+  blk -= data->block_per_zone;
+  if (blk < (grub_uint64_t) data->block_per_zone * (grub_uint64_t) data->block_per_zone)
     {
       indir = grub_get_indir (data, GRUB_MINIX_INODE_DINDIR_ZONE (data),
-			      blk / block_per_zone);
+			      blk / data->block_per_zone);
 
-      indir = grub_get_indir (data, indir, blk % block_per_zone);
+      indir = grub_get_indir (data, indir, blk % data->block_per_zone);
 
       return indir;
     }
 
 #if defined (MODE_MINIX3) || defined (MODE_MINIX2)
-  blk -= block_per_zone * block_per_zone;
-  if (blk < ((grub_uint64_t) block_per_zone * (grub_uint64_t) block_per_zone
-	     * (grub_uint64_t) block_per_zone))
+  blk -= data->block_per_zone * data->block_per_zone;
+  if (blk < ((grub_uint64_t) data->block_per_zone * (grub_uint64_t) data->block_per_zone
+	     * (grub_uint64_t) data->block_per_zone))
     {
       indir = grub_get_indir (data, grub_minix_to_cpu_n (data->inode.triple_indir_zone),
-			      (blk / block_per_zone) / block_per_zone);
-      indir = grub_get_indir (data, indir, (blk / block_per_zone) % block_per_zone);
-      indir = grub_get_indir (data, indir, blk % block_per_zone);
+			      (blk / data->block_per_zone) / data->block_per_zone);
+      indir = grub_get_indir (data, indir, (blk / data->block_per_zone) % data->block_per_zone);
+      indir = grub_get_indir (data, indir, blk % data->block_per_zone);
 
       return indir;
     }
@@ -262,6 +264,13 @@ grub_minix_read_file (struct grub_minix_data *data,
   grub_uint32_t posblock;
   grub_uint32_t blockoff;
 
+  if (pos > GRUB_MINIX_INODE_SIZE (data))
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE,
+		  N_("attempt to read past the end of file"));
+      return -1;
+    }
+
   /* Adjust len so it we can't read past the end of the file.  */
   if (len + pos > GRUB_MINIX_INODE_SIZE (data))
     len = GRUB_MINIX_INODE_SIZE (data) - pos;
@@ -278,7 +287,7 @@ grub_minix_read_file (struct grub_minix_data *data,
 
   for (i = posblock; i < blockcnt; i++)
     {
-      grub_disk_addr_t blknr;
+      grub_minix_uintn_t blknr;
       grub_uint64_t blockend = data->block_size << GRUB_DISK_SECTOR_BITS;
       grub_off_t skipfirst = 0;
 
@@ -307,7 +316,7 @@ grub_minix_read_file (struct grub_minix_data *data,
       data->disk->read_hook = read_hook;
       data->disk->read_hook_data = read_hook_data;
       grub_disk_read (data->disk,
-		      GRUB_MINIX_ZONE2SECT(blknr),
+		      grub_minix_zone2sect(data, blknr),
 		      skipfirst, blockend, buf);
       data->disk->read_hook = 0;
       if (grub_errno)
@@ -333,7 +342,8 @@ grub_minix_read_inode (struct grub_minix_data *data, grub_minix_ino_t ino)
 
   /* The first inode in minix is inode 1.  */
   ino--;
-  block = GRUB_MINIX_ZONE2SECT (2 + grub_minix_to_cpu16 (sblock->inode_bmap_size)
+  block = grub_minix_zone2sect (data,
+				2 + grub_minix_to_cpu16 (sblock->inode_bmap_size)
 				+ grub_minix_to_cpu16 (sblock->zone_bmap_size));
   block += ino / (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode));
   int offs = (ino % (GRUB_DISK_SECTOR_SIZE
@@ -508,6 +518,12 @@ grub_minix_mount (grub_disk_t disk)
   data->block_size = 2;
 #endif
 
+  data->block_per_zone = (((grub_uint64_t) data->block_size <<	\
+			   (GRUB_DISK_SECTOR_BITS + grub_minix_to_cpu16 (data->sblock.log2_zone_size)))
+			  / sizeof (grub_minix_uintn_t));
+  if (!data->block_per_zone)
+    goto fail;
+
   return data;
 
  fail:
diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c
index 388ee188e..598a2a55b 100644
--- a/grub-core/fs/nilfs2.c
+++ b/grub-core/fs/nilfs2.c
@@ -724,6 +724,10 @@ grub_nilfs2_valid_sb (struct grub_nilfs2_super_block *sbp)
   if (grub_le_to_cpu32 (sbp->s_rev_level) != NILFS_SUPORT_REV)
     return 0;
 
+  /* 20 already means 1GiB blocks. We don't want to deal with blocks overflowing int32. */
+  if (grub_le_to_cpu32 (sbp->s_log_block_size) > 20)
+    return 0;
+
   return 1;
 }
 
diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
index d3a91f5d7..6f8468862 100644
--- a/grub-core/fs/ntfs.c
+++ b/grub-core/fs/ntfs.c
@@ -618,7 +618,10 @@ list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos,
 
 	  ustr = get_utf8 (np, ns);
 	  if (ustr == NULL)
-	    return 0;
+	    {
+	      grub_free (fdiro);
+	      return 0;
+	    }
           if (namespace)
             type |= GRUB_FSHELP_CASE_INSENSITIVE;
 
@@ -917,12 +920,16 @@ grub_ntfs_mount (grub_disk_t disk)
 
   if (bpb.clusters_per_mft > 0)
     data->mft_size = ((grub_disk_addr_t) bpb.clusters_per_mft) << data->log_spc;
+  else if (-bpb.clusters_per_mft < GRUB_NTFS_BLK_SHR || -bpb.clusters_per_mft >= 31)
+    goto fail;
   else
     data->mft_size = 1ULL << (-bpb.clusters_per_mft - GRUB_NTFS_BLK_SHR);
 
   if (bpb.clusters_per_index > 0)
     data->idx_size = (((grub_disk_addr_t) bpb.clusters_per_index)
 		      << data->log_spc);
+  else if (-bpb.clusters_per_index < GRUB_NTFS_BLK_SHR || -bpb.clusters_per_index >= 31)
+    goto fail;
   else
     data->idx_size = 1ULL << (-bpb.clusters_per_index - GRUB_NTFS_BLK_SHR);
 
diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c
index de3d4fa3c..b78166554 100644
--- a/grub-core/fs/reiserfs.c
+++ b/grub-core/fs/reiserfs.c
@@ -1090,7 +1090,7 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node,
       switch (found.type)
         {
         case GRUB_REISERFS_DIRECT:
-          block = found.block_number * (block_size  >> GRUB_DISK_SECTOR_BITS);
+          block = ((grub_disk_addr_t) found.block_number) * (block_size  >> GRUB_DISK_SECTOR_BITS);
           grub_dprintf ("reiserfs_blocktype", "D: %u\n", (unsigned) block);
           if (initial_position < current_position + item_size)
             {
diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c
index 6c8215048..57b8d8da6 100644
--- a/grub-core/fs/sfs.c
+++ b/grub-core/fs/sfs.c
@@ -173,10 +173,11 @@ grub_sfs_read_extent (struct grub_sfs_data *data, unsigned int block,
   struct grub_sfs_btree *tree;
   int i;
   grub_uint32_t next;
+  grub_size_t blocksize = GRUB_DISK_SECTOR_SIZE << data->log_blocksize;
 
-  treeblock = grub_malloc (GRUB_DISK_SECTOR_SIZE << data->log_blocksize);
-  if (!block)
-    return 0;
+  treeblock = grub_malloc (blocksize);
+  if (!treeblock)
+    return grub_errno;
 
   next = grub_be_to_cpu32 (data->rblock.btree);
   tree = (struct grub_sfs_btree *) treeblock;
@@ -184,17 +185,21 @@ grub_sfs_read_extent (struct grub_sfs_data *data, unsigned int block,
   /* Handle this level in the btree.  */
   do
     {
+      grub_uint16_t nnodes;
       grub_disk_read (data->disk,
 		      ((grub_disk_addr_t) next) << data->log_blocksize,
-		      0, GRUB_DISK_SECTOR_SIZE << data->log_blocksize,
-		      treeblock);
+		      0, blocksize, treeblock);
       if (grub_errno)
 	{
 	  grub_free (treeblock);
 	  return grub_errno;
 	}
 
-      for (i = grub_be_to_cpu16 (tree->nodes) - 1; i >= 0; i--)
+      nnodes = grub_be_to_cpu16 (tree->nodes);
+      if (nnodes * (grub_uint32_t) (tree)->nodesize > blocksize)
+	break;
+
+      for (i = (int) nnodes - 1; i >= 0; i--)
 	{
 
 #define EXTNODE(tree, index)						\
diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c
index fd412830c..839bff889 100644
--- a/grub-core/fs/udf.c
+++ b/grub-core/fs/udf.c
@@ -986,6 +986,7 @@ grub_udf_read_symlink (grub_fshelp_node_t node)
 	case 1:
 	  if (ptr[1])
 	    goto fail;
+	  /* Fallthrough.  */
 	case 2:
 	  /* in 4 bytes. out: 1 byte.  */
 	  optr = out;
diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c
index 4a2161cc7..0619d6e32 100644
--- a/grub-core/fs/ufs.c
+++ b/grub-core/fs/ufs.c
@@ -465,7 +465,13 @@ grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino)
       && INODE_SIZE (data) <= sizeof (data->inode.symlink))
     grub_strcpy (symlink, (char *) data->inode.symlink);
   else
-    grub_ufs_read_file (data, 0, 0, 0, sz, symlink);
+    {
+      if (grub_ufs_read_file (data, 0, 0, 0, sz, symlink) < 0)
+	{
+	  grub_free(symlink);
+	  return grub_errno;
+	}
+    }
   symlink[sz] = '\0';
 
   /* The symlink is an absolute path, go back to the root inode.  */
@@ -604,7 +610,8 @@ grub_ufs_mount (grub_disk_t disk)
 	 endiannesses.  */
       if (data->sblock.magic == grub_cpu_to_ufs32_compile_time (GRUB_UFS_MAGIC)
 	  && data->sblock.bsize != 0
-	  && ((data->sblock.bsize & (data->sblock.bsize - 1)) == 0))
+	  && ((data->sblock.bsize & (data->sblock.bsize - 1)) == 0)
+	  && data->sblock.ino_per_group != 0)
 	{
 	  for (data->log2_blksz = 0; 
 	       (1U << data->log2_blksz) < grub_ufs_to_cpu32 (data->sblock.bsize);
diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
index cfb25c030..0cbb84bb3 100644
--- a/grub-core/fs/zfs/zfs.c
+++ b/grub-core/fs/zfs/zfs.c
@@ -252,7 +252,6 @@ struct grub_zfs_data
 
   uberblock_t current_uberblock;
 
-  int mounted;
   grub_uint64_t guid;
 };
 
@@ -286,7 +285,7 @@ static const char *spa_feature_names[] = {
 
 static int
 check_feature(const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx);
-static int
+static grub_err_t
 check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data );
 
 static grub_err_t 
@@ -957,7 +956,7 @@ nvpair_value (const char *nvp,char **val,
 static grub_err_t
 check_pool_label (struct grub_zfs_data *data,
 		  struct grub_zfs_device_desc *diskdesc,
-		  int *inserted)
+		  int *inserted, int original)
 {
   grub_uint64_t pool_state, txg = 0;
   char *nvlist,*features;
@@ -1081,11 +1080,12 @@ check_pool_label (struct grub_zfs_data *data,
 
   grub_dprintf ("zfs", "check 11 passed\n");
 
-  if (data->mounted && data->guid != poolguid)
-    return grub_error (GRUB_ERR_BAD_FS, "another zpool");
-  else
+  if (original)
     data->guid = poolguid;
 
+  if (data->guid != poolguid)
+    return grub_error (GRUB_ERR_BAD_FS, "another zpool");
+
   {
     char *nv;
     nv = grub_zfs_nvlist_lookup_nvlist (nvlist, ZPOOL_CONFIG_VDEV_TREE);
@@ -1186,7 +1186,7 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data,
 	}
       grub_dprintf ("zfs", "label ok %d\n", label);
 
-      err = check_pool_label (data, &desc, inserted);
+      err = check_pool_label (data, &desc, inserted, original);
       if (err || !*inserted)
 	{
 	  grub_errno = GRUB_ERR_NONE;
@@ -1501,6 +1501,9 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc,
 	  return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, 
 			     "raidz%d is not supported", desc->nparity);
 
+	if (desc->n_children <= desc->nparity || desc->n_children < 1)
+	  return grub_error(GRUB_ERR_BAD_FS, "too little devices for given parity");
+
 	orig_s = (((len + (1 << desc->ashift) - 1) >> desc->ashift)
 		  + (desc->n_children - desc->nparity) - 1);
 	s = orig_s;
@@ -1972,7 +1975,7 @@ dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf,
 						dn->endian) 
 	    << SPA_MINBLOCKSHIFT;
 	  *buf = grub_malloc (size);
-	  if (*buf)
+	  if (!*buf)
 	    {
 	      err = grub_errno;
 	      break;
@@ -2010,12 +2013,14 @@ dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf,
  */
 static grub_err_t
 mzap_lookup (mzap_phys_t * zapobj, grub_zfs_endian_t endian,
-	     int objsize, const char *name, grub_uint64_t * value,
+	     grub_uint16_t objsize, const char *name, grub_uint64_t * value,
 	     int case_insensitive)
 {
-  int i, chunks;
+  grub_uint16_t i, chunks;
   mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk;
 
+  if (objsize < MZAP_ENT_LEN)
+    return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), name);
   chunks = objsize / MZAP_ENT_LEN - 1;
   for (i = 0; i < chunks; i++)
     {
@@ -2423,7 +2428,7 @@ zap_lookup (dnode_end_t * zap_dnode, const char *name, grub_uint64_t *val,
 	    struct grub_zfs_data *data, int case_insensitive)
 {
   grub_uint64_t block_type;
-  int size;
+  grub_uint16_t size;
   void *zapbuf;
   grub_err_t err;
   grub_zfs_endian_t endian;
@@ -2804,6 +2809,9 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
 					  dnode_path->dn.endian)
 		       << SPA_MINBLOCKSHIFT);
 
+	      if (blksz == 0)
+		return grub_error(GRUB_ERR_BAD_FS, "0-sized block");
+
 	      sym_value = grub_malloc (sym_sz);
 	      if (!sym_value)
 		return grub_errno;
@@ -2829,6 +2837,8 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
 	  if (!path_buf)
 	    {
 	      grub_free (oldpathbuf);
+	      if (free_symval)
+		grub_free (sym_value);
 	      return grub_errno;
 	    }
 	  grub_memcpy (path, sym_value, sym_sz);
@@ -3606,8 +3616,6 @@ zfs_mount (grub_device_t dev)
 					 ub_endian) >> 63) & 1;
   grub_free (osp);
 
-  data->mounted = 1;
-
   return data;
 }
 
@@ -3798,6 +3806,12 @@ grub_zfs_read (grub_file_t file, char *buf, grub_size_t len)
   blksz = grub_zfs_to_cpu16 (data->dnode.dn.dn_datablkszsec, 
 			     data->dnode.endian) << SPA_MINBLOCKSHIFT;
 
+  if (blksz == 0)
+    {
+      grub_error (GRUB_ERR_BAD_FS, "0-sized block");
+      return -1;
+    }
+
   /*
    * Entire Dnode is too big to fit into the space available.  We
    * will need to read it in chunks.  This could be optimized to
@@ -3969,7 +3983,12 @@ iterate_zap (const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx)
   dnode_end_t dn;
   grub_memset (&info, 0, sizeof (info));
 
-  dnode_get (&(ctx->data->subvol.mdn), val, 0, &dn, ctx->data);
+  err = dnode_get (&(ctx->data->subvol.mdn), val, 0, &dn, ctx->data);
+  if (err)
+    {
+      grub_print_error ();
+      return 0;
+    }
 
   if (dn.dn.dn_bonustype == DMU_OT_SA)
     {
@@ -4190,11 +4209,11 @@ check_feature (const char *name, grub_uint64_t val,
  *	errnum: Failure.
  */
 	    	   
-static int
+static grub_err_t
 check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data )
 {
   grub_uint64_t objnum;
-  grub_uint8_t errnum = 0;
+  grub_err_t errnum = 0;
   dnode_end_t dn,mosmdn;
   mzap_phys_t* mzp;
   grub_zfs_endian_t endianzap;
diff --git a/grub-core/fs/zfs/zfscrypt.c b/grub-core/fs/zfs/zfscrypt.c
index 88dae72ef..87eef621d 100644
--- a/grub-core/fs/zfs/zfscrypt.c
+++ b/grub-core/fs/zfs/zfscrypt.c
@@ -238,7 +238,7 @@ grub_gcm_decrypt (grub_crypto_cipher_handle_t cipher,
       grub_crypto_xor (out + 16 * i, in + 16 * i, mul, csize);
     }
   for (j = 0; j < 8; j++)
-    mac[15 - j] ^= ((psize * 8) >> (8 * j));
+    mac[15 - j] ^= ((((grub_uint64_t) psize) * 8) >> (8 * j));
   grub_gcm_mul (mac, h);
 
   if (mac_out)
@@ -354,6 +354,7 @@ grub_zfs_load_key_real (const struct grub_zfs_key *key,
       if (err)
 	{
 	  grub_errno = GRUB_ERR_NONE;
+	  grub_crypto_cipher_close (cipher);
 	  continue;
 	}
 		    
@@ -362,6 +363,7 @@ grub_zfs_load_key_real (const struct grub_zfs_key *key,
       if (err)
 	{
 	  grub_errno = GRUB_ERR_NONE;
+	  grub_crypto_cipher_close (cipher);
 	  continue;
 	}
       
@@ -372,6 +374,7 @@ grub_zfs_load_key_real (const struct grub_zfs_key *key,
 	{
 	  grub_dprintf ("zfs", "key loading failed\n");
 	  grub_errno = GRUB_ERR_NONE;
+	  grub_crypto_cipher_close (cipher);
 	  continue;
 	}
 
@@ -381,21 +384,25 @@ grub_zfs_load_key_real (const struct grub_zfs_key *key,
 	{
 	  grub_dprintf ("zfs", "key loading failed\n");
 	  grub_errno = GRUB_ERR_NONE;
+	  grub_crypto_cipher_close (cipher);
 	  continue;
 	}
       ret = grub_crypto_cipher_open (GRUB_CIPHER_AES);
       if (!ret)
 	{
 	  grub_errno = GRUB_ERR_NONE;
+	  grub_crypto_cipher_close (cipher);
 	  continue;
 	}
       err = grub_crypto_cipher_set_key (ret, decrypted, keylen);
       if (err)
 	{
-	    grub_errno = GRUB_ERR_NONE;
-	    grub_crypto_cipher_close (ret);
-	    continue;
-	  }
+	  grub_errno = GRUB_ERR_NONE;
+	  grub_crypto_cipher_close (ret);
+	  grub_crypto_cipher_close (cipher);
+	  continue;
+	}
+      grub_crypto_cipher_close (cipher);
       return ret;
     }
   return NULL;
diff --git a/grub-core/fs/zfs/zfsinfo.c b/grub-core/fs/zfs/zfsinfo.c
index c96bf2183..c8a28acf5 100644
--- a/grub-core/fs/zfs/zfsinfo.c
+++ b/grub-core/fs/zfs/zfsinfo.c
@@ -130,10 +130,12 @@ print_vdev_info (char *nvlist, int tab)
       grub_free (bootpath);
       grub_free (devid);
       grub_free (path);
+      grub_free (type);
       return GRUB_ERR_NONE;
     }
   char is_mirror=(grub_strcmp(type,VDEV_TYPE_MIRROR) == 0);
   char is_raidz=(grub_strcmp(type,VDEV_TYPE_RAIDZ) == 0);
+  grub_free (type);
 
   if (is_mirror || is_raidz)
     {
diff --git a/grub-core/gfxmenu/gui_circular_progress.c b/grub-core/gfxmenu/gui_circular_progress.c
index 04f68b8d3..354dd7b73 100644
--- a/grub-core/gfxmenu/gui_circular_progress.c
+++ b/grub-core/gfxmenu/gui_circular_progress.c
@@ -138,51 +138,53 @@ circprog_paint (void *vself, const grub_video_rect_t *region)
                           (height - center_height) / 2, 0, 0,
                           center_width, center_height);
 
-  int radius = grub_min (height, width) / 2 - grub_max (tick_height, tick_width) / 2 - 1;
-  unsigned nticks;
-  unsigned tick_begin;
-  unsigned tick_end;
-  if (self->end <= self->start
-      || self->value <= self->start)
-    nticks = 0;
-  else
-    nticks = ((unsigned) (self->num_ticks
-			  * (self->value - self->start)))
-      / ((unsigned) (self->end - self->start));
-  /* Do ticks appear or disappear as the value approached the end?  */
-  if (self->ticks_disappear)
+  if (self->num_ticks)
     {
-      tick_begin = nticks;
-      tick_end = self->num_ticks;
+      int radius = grub_min (height, width) / 2 - grub_max (tick_height, tick_width) / 2 - 1;
+      unsigned nticks;
+      unsigned tick_begin;
+      unsigned tick_end;
+      if (self->end <= self->start
+	  || self->value <= self->start)
+	nticks = 0;
+      else
+	nticks = ((unsigned) (self->num_ticks
+			      * (self->value - self->start)))
+	  / ((unsigned) (self->end - self->start));
+      /* Do ticks appear or disappear as the value approached the end?  */
+      if (self->ticks_disappear)
+	{
+	  tick_begin = nticks;
+	  tick_end = self->num_ticks;
+	}
+      else
+	{
+	  tick_begin = 0;
+	  tick_end = nticks;
+	}
+
+      unsigned i;
+      for (i = tick_begin; i < tick_end; i++)
+	{
+	  int x;
+	  int y;
+	  int angle;
+
+	  /* Calculate the location of the tick.  */
+	  angle = self->start_angle
+	    + i * GRUB_TRIG_ANGLE_MAX / self->num_ticks;
+	  x = width / 2 + (grub_cos (angle) * radius / GRUB_TRIG_FRACTION_SCALE);
+	  y = height / 2 + (grub_sin (angle) * radius / GRUB_TRIG_FRACTION_SCALE);
+
+	  /* Adjust (x,y) so the tick is centered.  */
+	  x -= tick_width / 2;
+	  y -= tick_height / 2;
+
+	  /* Draw the tick.  */
+	  grub_video_blit_bitmap (self->tick_bitmap, GRUB_VIDEO_BLIT_BLEND,
+				  x, y, 0, 0, tick_width, tick_height);
+	}
     }
-  else
-    {
-      tick_begin = 0;
-      tick_end = nticks;
-    }
-
-  unsigned i;
-  for (i = tick_begin; i < tick_end; i++)
-    {
-       int x;
-       int y;
-       int angle;
-
-       /* Calculate the location of the tick.  */
-       angle = self->start_angle
-	 + i * GRUB_TRIG_ANGLE_MAX / self->num_ticks;
-       x = width / 2 + (grub_cos (angle) * radius / GRUB_TRIG_FRACTION_SCALE);
-       y = height / 2 + (grub_sin (angle) * radius / GRUB_TRIG_FRACTION_SCALE);
-
-       /* Adjust (x,y) so the tick is centered.  */
-       x -= tick_width / 2;
-       y -= tick_height / 2;
-
-       /* Draw the tick.  */
-       grub_video_blit_bitmap (self->tick_bitmap, GRUB_VIDEO_BLIT_BLEND,
-                               x, y, 0, 0, tick_width, tick_height);
-    }
-
   grub_gui_restore_viewport (&vpsave);
 }
 
diff --git a/grub-core/gfxmenu/gui_list.c b/grub-core/gfxmenu/gui_list.c
index 5d26811f9..01477cdf2 100644
--- a/grub-core/gfxmenu/gui_list.c
+++ b/grub-core/gfxmenu/gui_list.c
@@ -131,6 +131,9 @@ get_num_shown_items (list_impl_t self)
   int max_top_pad = grub_max (item_top_pad, sel_top_pad);
   int max_bottom_pad = grub_max (item_bottom_pad, sel_bottom_pad);
 
+  if (item_height + item_vspace <= 0)
+    return 1;
+
   return (self->bounds.height + item_vspace - 2 * boxpad
           - max_top_pad - max_bottom_pad
           - box_top_pad - box_bottom_pad) / (item_height + item_vspace);
diff --git a/grub-core/gfxmenu/gui_progress_bar.c b/grub-core/gfxmenu/gui_progress_bar.c
index 3501b0172..b128f0866 100644
--- a/grub-core/gfxmenu/gui_progress_bar.c
+++ b/grub-core/gfxmenu/gui_progress_bar.c
@@ -118,9 +118,15 @@ draw_filled_rect_bar (grub_gui_progress_bar_t self)
                         f.width + 2, f.height + 2);
 
   /* Bar background.  */
-  int barwidth = (f.width
-                  * (self->value - self->start)
-                  / (self->end - self->start));
+  unsigned barwidth;
+
+  if (self->end <= self->start
+      || self->value <= self->start)
+    barwidth = 0;
+  else
+    barwidth = (f.width
+		* (self->value - self->start)
+		/ (self->end - self->start));
   grub_video_fill_rect (grub_video_map_rgba_color (self->bg_color),
                         f.x + barwidth, f.y,
                         f.width - barwidth, f.height);
diff --git a/grub-core/gfxmenu/icon_manager.c b/grub-core/gfxmenu/icon_manager.c
index ff49ab0e0..1894682ef 100644
--- a/grub-core/gfxmenu/icon_manager.c
+++ b/grub-core/gfxmenu/icon_manager.c
@@ -106,8 +106,10 @@ grub_gfxmenu_icon_manager_set_theme_path (grub_gfxmenu_icon_manager_t mgr,
                                           const char *path)
 {
   /* Clear the cache if the theme path has changed.  */
-  if (((mgr->theme_path == 0) != (path == 0))
-      || (grub_strcmp (mgr->theme_path, path) != 0))
+  if (mgr->theme_path == 0 && path == 0)
+    return;
+  if (mgr->theme_path == 0 || path == 0
+      || grub_strcmp (mgr->theme_path, path) != 0)
     grub_gfxmenu_icon_manager_clear_cache (mgr);
 
   grub_free (mgr->theme_path);
diff --git a/grub-core/gfxmenu/theme_loader.c b/grub-core/gfxmenu/theme_loader.c
index 8a7945816..1a6ed1d25 100644
--- a/grub-core/gfxmenu/theme_loader.c
+++ b/grub-core/gfxmenu/theme_loader.c
@@ -774,6 +774,8 @@ grub_gfxmenu_view_load_theme (grub_gfxmenu_view_t view, const char *theme_path)
     view->canvas->component.ops->destroy (view->canvas);
 
   view->canvas = grub_gui_canvas_new ();
+  if (!view->canvas)
+    goto fail;
   ((grub_gui_component_t) view->canvas)
     ->ops->set_bounds ((grub_gui_component_t) view->canvas,
                        &view->screen);
diff --git a/grub-core/gnulib/argp-help.c b/grub-core/gnulib/argp-help.c
index 2914f4723..b9be63f40 100644
--- a/grub-core/gnulib/argp-help.c
+++ b/grub-core/gnulib/argp-help.c
@@ -1,5 +1,5 @@
 /* Hierarchical argument parsing help output
-   Copyright (C) 1995-2005, 2007, 2009-2013 Free Software Foundation, Inc.
+   Copyright (C) 1995-2005, 2007, 2009-2015 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Miles Bader <miles@gnu.ai.mit.edu>.
 
@@ -650,7 +650,7 @@ hol_find_entry (struct hol *hol, const char *name)
   return 0;
 }
 
-/* If an entry with the long option NAME occurs in HOL, set it's special
+/* If an entry with the long option NAME occurs in HOL, set its special
    sort position to GROUP.  */
 static void
 hol_set_group (struct hol *hol, const char *name, int group)
@@ -1507,11 +1507,15 @@ argp_doc (const struct argp *argp, const struct argp_state *state,
       if (vt)
         {
           if (post)
-            inp_text = vt + 1;
+            {
+              inp_text = vt + 1;
+              if (! *inp_text)
+                inp_text = 0;
+            }
           else
             {
               inp_text_len = vt - argp->doc;
-              inp_text = __strndup (argp->doc, inp_text_len);
+              inp_text = inp_text_len ? __strndup (argp->doc, inp_text_len) : 0;
             }
         }
       else
diff --git a/grub-core/io/gzio.c b/grub-core/io/gzio.c
index 129209e37..0f2ea6bd8 100644
--- a/grub-core/io/gzio.c
+++ b/grub-core/io/gzio.c
@@ -1161,6 +1161,19 @@ grub_gzio_open (grub_file_t io, const char *name __attribute__ ((unused)))
   return file;
 }
 
+static grub_uint8_t
+mod_31 (grub_uint16_t v)
+{
+  /* At most 2 iterations for any number that
+     we can get here.
+     In any case faster than real division.  */
+  while (v > 0x1f)
+    v = (v & 0x1f) + (v >> 5);
+  if (v == 0x1f)
+    return 0;
+  return v;
+}
+
 static int
 test_zlib_header (grub_gzio_t gzio)
 {
@@ -1178,7 +1191,10 @@ test_zlib_header (grub_gzio_t gzio)
       return 0;
     }
 
-  if ((cmf * 256U + flg) % 31U)
+  /* Usually it would be: (cmf * 256 + flg) % 31 != 0.  */
+  /* But 256 == 8 (31).  */
+  /* By multiplying by 4 and using 32 == 1 (31). We get our formula.  */
+  if (mod_31 (cmf + flg * 4) != 0)
     {
       grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, N_("unsupported gzip format"));
       return 0;
diff --git a/grub-core/io/lzopio.c b/grub-core/io/lzopio.c
index de2ea6778..7559c6c9c 100644
--- a/grub-core/io/lzopio.c
+++ b/grub-core/io/lzopio.c
@@ -403,8 +403,6 @@ test_header (grub_file_t file)
   return 1;
 
 CORRUPTED:
-  grub_free(name);
-
   return 0;
 }
 
diff --git a/grub-core/kern/arm/misc.S b/grub-core/kern/arm/compiler-rt.S
similarity index 79%
rename from grub-core/kern/arm/misc.S
rename to grub-core/kern/arm/compiler-rt.S
index 8943cc302..645b42f50 100644
--- a/grub-core/kern/arm/misc.S
+++ b/grub-core/kern/arm/compiler-rt.S
@@ -58,25 +58,22 @@ FUNCTION(__aeabi_lmul)
         ldmfd   sp!, {r4, fp}
         bx      lr
 
-	.macro division parent
+	.macro division32 parent
 
-        stmfd   sp!, {lr}
-        sub     sp, sp, #12
-        mov     r2, r1
-        add     r1, sp, #4
-        str     r1, [sp, #0]
-        mov     r1, #0
-        mov     r3, #0
+        sub     sp, sp, #8      @ Allocate naturally aligned 64-bit space
+        stmfd   sp!, {r3,lr}    @ Dummy r3 to maintain stack alignment
+        add     r2, sp, #8      @ Set r2 to address of 64-bit space
         bl      \parent
-	ldr     r1, [sp, #4]
-        add     sp, sp, #12
-        ldmfd   sp!, {lr}
+        ldr     r1, [sp, #8]    @ Extract remainder
+        ldmfd   sp!, {r3,lr}    @ Pop into an unused arg/scratch register
+        add     sp, sp, #8
         bx      lr
 	.endm
 
 FUNCTION(__aeabi_uidivmod)
-	division grub_divmod64
-
+	division32 grub_divmod32
+FUNCTION(__aeabi_idivmod)
+	division32 grub_divmod32s
 
 /*
  * Null divide-by-zero handler
diff --git a/grub-core/kern/arm/dl.c b/grub-core/kern/arm/dl.c
index 57cac2e75..24364e189 100644
--- a/grub-core/kern/arm/dl.c
+++ b/grub-core/kern/arm/dl.c
@@ -78,9 +78,9 @@ grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
 	const Elf_Rel *rel, *max;
 
 	for (rel = (const Elf_Rel *) ((grub_addr_t) e + s->sh_offset),
-	       max = rel + s->sh_size / s->sh_entsize;
-	     rel < max;
-	     rel++)
+	       max = (const Elf_Rel *) ((grub_addr_t) rel + s->sh_size);
+	     rel + 1 <= max;
+	     rel = (const Elf_Rel *) ((grub_addr_t) rel + s->sh_entsize))
 	  switch (ELF_R_TYPE (rel->r_info))
 	    {
 	    case R_ARM_CALL:
@@ -205,6 +205,21 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
 	   */
 	case R_ARM_V4BX:
 	  break;
+	case R_ARM_THM_MOVW_ABS_NC:
+	case R_ARM_THM_MOVT_ABS:
+	  {
+	    grub_uint32_t offset;
+	    offset = grub_arm_thm_movw_movt_get_value((grub_uint16_t *) target);
+	    offset += sym_addr;
+
+	    if (ELF_R_TYPE (rel->r_info) == R_ARM_THM_MOVT_ABS)
+	      offset >>= 16;
+	    else
+	      offset &= 0xffff;
+
+	    grub_arm_thm_movw_movt_set_value((grub_uint16_t *) target, offset);
+	  }
+	  break;
 	case R_ARM_THM_JUMP19:
 	  {
 	    /* Thumb instructions can be 16-bit aligned */
diff --git a/grub-core/kern/arm/dl_helper.c b/grub-core/kern/arm/dl_helper.c
index 5721939c1..21d77f763 100644
--- a/grub-core/kern/arm/dl_helper.c
+++ b/grub-core/kern/arm/dl_helper.c
@@ -25,6 +25,20 @@
 #include <grub/i18n.h>
 #include <grub/arm/reloc.h>
 
+static inline grub_uint32_t
+thumb_get_instruction_word (grub_uint16_t *target)
+{
+  /* Extract instruction word in alignment-safe manner */
+  return grub_le_to_cpu16 ((*target)) << 16 | grub_le_to_cpu16 (*(target + 1));
+}
+
+static inline void
+thumb_set_instruction_word (grub_uint16_t *target, grub_uint32_t insword)
+{
+  *target = grub_cpu_to_le16 (insword >> 16);
+  *(target + 1) = grub_cpu_to_le16 (insword & 0xffff);
+}
+
 /*
  * R_ARM_ABS32
  *
@@ -56,9 +70,7 @@ grub_arm_thm_call_get_offset (grub_uint16_t *target)
   grub_uint32_t insword;
   grub_int32_t offset;
 
-  /* Extract instruction word in alignment-safe manner */
-  insword = (grub_le_to_cpu16 (*target) << 16)
-    | (grub_le_to_cpu16(*(target + 1)));
+  insword = thumb_get_instruction_word (target);
 
   /* Extract bitfields from instruction words */
   sign = (insword >> 26) & 1;
@@ -83,9 +95,7 @@ grub_arm_thm_call_set_offset (grub_uint16_t *target, grub_int32_t offset)
   grub_uint32_t insword;
   int is_blx;
 
-  /* Extract instruction word in alignment-safe manner */
-  insword = (grub_le_to_cpu16 (*target) << 16)
-    | (grub_le_to_cpu16(*(target + 1)));
+  insword = thumb_get_instruction_word (target);
 
   if (((insword >> 12) & 0xd) == 0xc)
     is_blx = 1;
@@ -108,9 +118,7 @@ grub_arm_thm_call_set_offset (grub_uint16_t *target, grub_int32_t offset)
     (((offset >> 12) & 0x03ff) << 16) |
     (j1 << 13) | (j2 << 11) | ((offset >> 1) & 0x07ff);
 
-  /* Write instruction word back in alignment-safe manner */
-  *target = grub_cpu_to_le16 ((insword >> 16) & 0xffff);
-  *(target + 1) = grub_cpu_to_le16 (insword & 0xffff);
+  thumb_set_instruction_word (target, insword);
 
   grub_dprintf ("dl", "    *insword = 0x%08x", insword);
 
@@ -123,9 +131,7 @@ grub_arm_thm_jump19_get_offset (grub_uint16_t *target)
   grub_int32_t offset;
   grub_uint32_t insword;
 
-  /* Extract instruction word in alignment-safe manner */
-  insword = (grub_le_to_cpu16 (*target) << 16)
-    | (grub_le_to_cpu16(*(target + 1)));
+  insword = thumb_get_instruction_word (target);
 
   /* Extract and sign extend offset */
   offset = ((insword >> 26) & 1) << 19
@@ -149,9 +155,7 @@ grub_arm_thm_jump19_set_offset (grub_uint16_t *target, grub_int32_t offset)
   offset >>= 1;
   offset &= 0xfffff;
 
-  /* Extract instruction word in alignment-safe manner */
-  insword = grub_le_to_cpu16 ((*target)) << 16
-    | grub_le_to_cpu16 (*(target + 1));
+  insword = thumb_get_instruction_word (target);
 
   /* Reassemble instruction word and write back */
   insword &= insmask;
@@ -160,8 +164,7 @@ grub_arm_thm_jump19_set_offset (grub_uint16_t *target, grub_int32_t offset)
     | ((offset >> 17) & 1) << 13
     | ((offset >> 11) & 0x3f) << 16
     | (offset & 0x7ff);
-  *target = grub_cpu_to_le16 (insword >> 16);
-  *(target + 1) = grub_cpu_to_le16 (insword & 0xffff);
+  thumb_set_instruction_word (target, insword);
 }
 
 int
@@ -172,6 +175,32 @@ grub_arm_thm_jump19_check_offset (grub_int32_t offset)
   return 1;
 }
 
+grub_uint16_t
+grub_arm_thm_movw_movt_get_value (grub_uint16_t *target)
+{
+  grub_uint32_t insword;
+
+  insword = thumb_get_instruction_word (target);
+
+  return ((insword & 0xf0000) >> 4) | ((insword & 0x04000000) >> 15) | \
+    ((insword & 0x7000) >> 4) | (insword & 0xff);
+}
+
+void
+grub_arm_thm_movw_movt_set_value (grub_uint16_t *target, grub_uint16_t value)
+{
+  grub_uint32_t insword;
+  const grub_uint32_t insmask = 0xfbf08f00;
+
+  insword = thumb_get_instruction_word (target);
+  insword &= insmask;
+
+  insword |= ((value & 0xf000) << 4) | ((value & 0x0800) << 15) | \
+    ((value & 0x0700) << 4) | (value & 0xff);
+
+  thumb_set_instruction_word (target, insword);
+}
+
 
 /***********************************************************
  * ARM (A32) relocations:                                  *
diff --git a/grub-core/kern/compiler-rt.c b/grub-core/kern/compiler-rt.c
new file mode 100644
index 000000000..d4cc15513
--- /dev/null
+++ b/grub-core/kern/compiler-rt.c
@@ -0,0 +1,404 @@
+/* compiler-rt.c - compiler helpers. */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004,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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/misc.h>
+#include <grub/compiler-rt.h>
+
+#ifndef GRUB_EMBED_DECOMPRESSOR
+void * GRUB_BUILTIN_ATTR
+memcpy (void *dest, const void *src, grub_size_t n)
+{
+	return grub_memmove (dest, src, n);
+}
+void * GRUB_BUILTIN_ATTR
+memmove (void *dest, const void *src, grub_size_t n)
+{
+	return grub_memmove (dest, src, n);
+}
+int GRUB_BUILTIN_ATTR
+memcmp (const void *s1, const void *s2, grub_size_t n)
+{
+  return grub_memcmp (s1, s2, n);
+}
+void * GRUB_BUILTIN_ATTR
+memset (void *s, int c, grub_size_t n)
+{
+  return grub_memset (s, c, n);
+}
+
+#ifdef __APPLE__
+
+void GRUB_BUILTIN_ATTR
+__bzero (void *s, grub_size_t n)
+{
+  grub_memset (s, 0, n);
+}
+
+#endif
+
+#if GRUB_DIVISION_IN_SOFTWARE
+
+grub_uint32_t
+__udivsi3 (grub_uint32_t a, grub_uint32_t b)
+{
+  return grub_divmod64 (a, b, 0);
+}
+
+grub_int32_t
+__divsi3 (grub_int32_t a, grub_int32_t b)
+{
+  return grub_divmod64s (a, b, 0);
+}
+
+grub_uint32_t
+__umodsi3 (grub_uint32_t a, grub_uint32_t b)
+{
+  grub_uint64_t ret;
+  grub_divmod64 (a, b, &ret);
+  return ret;
+}
+
+grub_int32_t
+__modsi3 (grub_int32_t a, grub_int32_t b)
+{
+  grub_int64_t ret;
+  grub_divmod64s (a, b, &ret);
+  return ret;
+}
+
+grub_uint64_t
+__udivdi3 (grub_uint64_t a, grub_uint64_t b)
+{
+  return grub_divmod64 (a, b, 0);
+}
+
+grub_uint64_t
+__umoddi3 (grub_uint64_t a, grub_uint64_t b)
+{
+  grub_uint64_t ret;
+  grub_divmod64 (a, b, &ret);
+  return ret;
+}
+
+grub_int64_t
+__divdi3 (grub_int64_t a, grub_int64_t b)
+{
+  return grub_divmod64s (a, b, 0);
+}
+
+grub_int64_t
+__moddi3 (grub_int64_t a, grub_int64_t b)
+{
+  grub_int64_t ret;
+  grub_divmod64s (a, b, &ret);
+  return ret;
+}
+
+#endif
+
+#endif
+
+#ifdef NEED_CTZDI2
+
+unsigned
+__ctzdi2 (grub_uint64_t x)
+{
+  unsigned ret = 0;
+  if (!x)
+    return 64;
+  if (!(x & 0xffffffff))
+    {
+      x >>= 32;
+      ret |= 32;
+    }
+  if (!(x & 0xffff))
+    {
+      x >>= 16;
+      ret |= 16;
+    }
+  if (!(x & 0xff))
+    {
+      x >>= 8;
+      ret |= 8;
+    }
+  if (!(x & 0xf))
+    {
+      x >>= 4;
+      ret |= 4;
+    }
+  if (!(x & 0x3))
+    {
+      x >>= 2;
+      ret |= 2;
+    }
+  if (!(x & 0x1))
+    {
+      x >>= 1;
+      ret |= 1;
+    }
+  return ret;
+}
+#endif
+
+#ifdef NEED_CTZSI2
+unsigned
+__ctzsi2 (grub_uint32_t x)
+{
+  unsigned ret = 0;
+  if (!x)
+    return 32;
+
+  if (!(x & 0xffff))
+    {
+      x >>= 16;
+      ret |= 16;
+    }
+  if (!(x & 0xff))
+    {
+      x >>= 8;
+      ret |= 8;
+    }
+  if (!(x & 0xf))
+    {
+      x >>= 4;
+      ret |= 4;
+    }
+  if (!(x & 0x3))
+    {
+      x >>= 2;
+      ret |= 2;
+    }
+  if (!(x & 0x1))
+    {
+      x >>= 1;
+      ret |= 1;
+    }
+  return ret;
+}
+
+#endif
+
+
+#if defined (__clang__) && !defined(GRUB_EMBED_DECOMPRESSOR)
+/* clang emits references to abort().  */
+void __attribute__ ((noreturn))
+abort (void)
+{
+  grub_fatal ("compiler abort");
+}
+#endif
+
+#if (defined (__MINGW32__) || defined (__CYGWIN__))
+void __register_frame_info (void)
+{
+}
+
+void __deregister_frame_info (void)
+{
+}
+
+void ___chkstk_ms (void)
+{
+}
+
+void __chkstk_ms (void)
+{
+}
+#endif
+
+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__) || defined (__arm__) || defined(__mips__)
+
+/* 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 = ((grub_int32_t) uu.high) >> (32 - 1);
+      w.low = ((grub_int32_t) uu.high) >> -bm;
+    }
+  else
+    {
+      const grub_uint32_t carries = ((grub_uint32_t) uu.high) << bm;
+
+      w.high = ((grub_int32_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
+__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;
+}
+
+/* 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;
+}
+
+#endif
+
+#if defined (__powerpc__) || defined(__mips__) || defined(__sparc__) || defined(__arm__)
+
+/* Based on libgcc2.c from gcc suite.  */
+grub_uint32_t
+__bswapsi2 (grub_uint32_t u)
+{
+  return ((((u) & 0xff000000) >> 24)
+	  | (((u) & 0x00ff0000) >>  8)
+	  | (((u) & 0x0000ff00) <<  8)
+	  | (((u) & 0x000000ff) << 24));
+}
+
+/* Based on libgcc2.c from gcc suite.  */
+grub_uint64_t
+__bswapdi2 (grub_uint64_t u)
+{
+  return ((((u) & 0xff00000000000000ull) >> 56)
+	  | (((u) & 0x00ff000000000000ull) >> 40)
+	  | (((u) & 0x0000ff0000000000ull) >> 24)
+	  | (((u) & 0x000000ff00000000ull) >>  8)
+	  | (((u) & 0x00000000ff000000ull) <<  8)
+	  | (((u) & 0x0000000000ff0000ull) << 24)
+	  | (((u) & 0x000000000000ff00ull) << 40)
+	  | (((u) & 0x00000000000000ffull) << 56));
+}
+
+
+#endif
+
+#ifdef __arm__
+grub_uint32_t
+__aeabi_uidiv (grub_uint32_t a, grub_uint32_t b)
+  __attribute__ ((alias ("__udivsi3")));
+grub_int32_t
+__aeabi_idiv (grub_int32_t a, grub_int32_t b)
+  __attribute__ ((alias ("__divsi3")));
+void *__aeabi_memcpy (void *dest, const void *src, grub_size_t n)
+  __attribute__ ((alias ("grub_memcpy")));
+void *__aeabi_memset (void *s, int c, grub_size_t n)
+  __attribute__ ((alias ("memset")));
+
+int
+__aeabi_ulcmp (grub_uint64_t a, grub_uint64_t b)
+{
+  return __ucmpdi2 (a, b) - 1;
+}
+
+grub_uint64_t
+__aeabi_lasr (grub_uint64_t u, int b)
+  __attribute__ ((alias ("__ashrdi3")));
+grub_uint64_t
+__aeabi_llsr (grub_uint64_t u, int b)
+  __attribute__ ((alias ("__lshrdi3")));
+
+grub_uint64_t
+__aeabi_llsl (grub_uint64_t u, int b)
+  __attribute__ ((alias ("__ashldi3")));
+
+#endif
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
index 80da8706f..7dcc852e5 100644
--- a/grub-core/kern/dl.c
+++ b/grub-core/kern/dl.c
@@ -348,7 +348,7 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e)
   mod->symtab = grub_malloc (s->sh_size);
   if (!mod->symtab)
     return grub_errno;
-  memcpy (mod->symtab, (char *) e + s->sh_offset, s->sh_size);
+  grub_memcpy (mod->symtab, (char *) e + s->sh_offset, s->sh_size);
 #else
   mod->symtab = (Elf_Sym *) ((char *) e + s->sh_offset);
 #endif
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
index ddeca6073..efb15cc1b 100644
--- a/grub-core/kern/efi/mm.c
+++ b/grub-core/kern/efi/mm.c
@@ -262,6 +262,7 @@ grub_efi_get_memory_map (grub_efi_uintn_t *memory_map_size,
   grub_efi_boot_services_t *b;
   grub_efi_uintn_t key;
   grub_efi_uint32_t version;
+  grub_efi_uintn_t size;
 
   if (grub_efi_is_finished)
     {
@@ -291,10 +292,14 @@ grub_efi_get_memory_map (grub_efi_uintn_t *memory_map_size,
     map_key = &key;
   if (! descriptor_version)
     descriptor_version = &version;
+  if (! descriptor_size)
+    descriptor_size = &size;
 
   b = grub_efi_system_table->boot_services;
   status = efi_call_5 (b->get_memory_map, memory_map_size, memory_map, map_key,
 			      descriptor_size, descriptor_version);
+  if (*descriptor_size == 0)
+    *descriptor_size = sizeof (grub_efi_memory_descriptor_t);
   if (status == GRUB_EFI_SUCCESS)
     return 1;
   else if (status == GRUB_EFI_BUFFER_TOO_SMALL)
diff --git a/grub-core/kern/emu/cache.c b/grub-core/kern/emu/cache.c
index 07be6756f..6f89e871a 100644
--- a/grub-core/kern/emu/cache.c
+++ b/grub-core/kern/emu/cache.c
@@ -8,7 +8,7 @@
 #include "../ia64/cache.c"
 #elif defined (__arm__) || defined (__aarch64__)
 
-void __clear_cache (char *beg, char *end);
+void __clear_cache (void *beg, void *end);
 
 void
 grub_arch_sync_caches (void *address, grub_size_t len)
diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c
index 44b0fcbb1..a3b00c8f6 100644
--- a/grub-core/kern/emu/hostdisk.c
+++ b/grub-core/kern/emu/hostdisk.c
@@ -99,7 +99,7 @@ find_free_slot (void)
 {
   unsigned int i;
 
-  for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
+  for (i = 0; i < ARRAY_SIZE (map); i++)
     if (! map[i].drive)
       return i;
 
@@ -115,7 +115,7 @@ grub_util_biosdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
   if (pull != GRUB_DISK_PULL_NONE)
     return 0;
 
-  for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
+  for (i = 0; i < ARRAY_SIZE (map); i++)
     if (map[i].drive && hook (map[i].drive, hook_data))
       return 1;
 
@@ -184,7 +184,7 @@ grub_hostdisk_os_dev_to_grub_drive (const char *os_disk, int add)
   unsigned int i;
   char *canon;
 
-  canon = canonicalize_file_name (os_disk);
+  canon = grub_canonicalize_file_name (os_disk);
   if (!canon)
     canon = xstrdup (os_disk);
 
@@ -535,7 +535,7 @@ read_device_map (const char *dev_map)
       /* On Linux, the devfs uses symbolic links horribly, and that
 	 confuses the interface very much, so use realpath to expand
 	 symbolic links.  */
-      map[drive].device = canonicalize_file_name (p);
+      map[drive].device = grub_canonicalize_file_name (p);
       if (! map[drive].device)
 	map[drive].device = xstrdup (p);
       
@@ -581,7 +581,7 @@ grub_util_biosdisk_fini (void)
 {
   unsigned i;
 
-  for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
+  for (i = 0; i < ARRAY_SIZE(map); i++)
     {
       if (map[i].drive)
 	free (map[i].drive);
diff --git a/grub-core/kern/emu/hostfs.c b/grub-core/kern/emu/hostfs.c
index 823116da6..7b28c001f 100644
--- a/grub-core/kern/emu/hostfs.c
+++ b/grub-core/kern/emu/hostfs.c
@@ -19,11 +19,6 @@
 
 #include <config-util.h>
 
-/* Legacy feature macro.*/
-#define _BSD_SOURCE
-/* New feature macro that provides everything _BSD_SOURCE and
- *    _SVID_SOURCE provided and possibly more.  */
-#define _DEFAULT_SOURCE
 #include <grub/fs.h>
 #include <grub/file.h>
 #include <grub/disk.h>
diff --git a/grub-core/kern/generic/rtc_get_time_ms.c b/grub-core/kern/generic/rtc_get_time_ms.c
index 49f2acac9..3e39c8fe1 100644
--- a/grub-core/kern/generic/rtc_get_time_ms.c
+++ b/grub-core/kern/generic/rtc_get_time_ms.c
@@ -34,5 +34,5 @@ grub_rtc_get_time_ms (void)
         1 s          1        T rtc ticks
    */
   grub_uint64_t ticks_ms_per_sec = ((grub_uint64_t) 1000) * grub_get_rtc ();
-  return grub_divmod64 (ticks_ms_per_sec, GRUB_TICKS_PER_SECOND, 0);
+  return grub_divmod64 (ticks_ms_per_sec, GRUB_TICKS_PER_SECOND ? : 1000, 0);
 }
diff --git a/grub-core/kern/i386/coreboot/startup.S b/grub-core/kern/i386/coreboot/startup.S
index 8c3283846..c8486548d 100644
--- a/grub-core/kern/i386/coreboot/startup.S
+++ b/grub-core/kern/i386/coreboot/startup.S
@@ -61,8 +61,3 @@ multiboot_header:
 	/* checksum */
 	.long	-0x1BADB002 - MULTIBOOT_MEMORY_INFO
 
-/*
- *  prot_to_real and associated structures (but NOT real_to_prot, that is
- *  only needed for BIOS gates).
- */
-#include "../realmode.S"
diff --git a/grub-core/kern/i386/pc/mmap.c b/grub-core/kern/i386/pc/mmap.c
index f1375f3e1..c0c3c3585 100644
--- a/grub-core/kern/i386/pc/mmap.c
+++ b/grub-core/kern/i386/pc/mmap.c
@@ -148,7 +148,7 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
 
   while (1)
     {
-      grub_memset (entry, 0, sizeof (entry));
+      grub_memset (entry, 0, sizeof (*entry));
 
       cont = grub_get_mmap_entry (entry, cont);
 
diff --git a/grub-core/kern/i386/pc/startup.S b/grub-core/kern/i386/pc/startup.S
index 6bb36c603..b8a9b33b4 100644
--- a/grub-core/kern/i386/pc/startup.S
+++ b/grub-core/kern/i386/pc/startup.S
@@ -135,7 +135,7 @@ LOCAL(prot_to_real_addr):
 
 	.macro REAL_TO_PROT
 	movl	LOCAL(real_to_prot_addr), %eax
-	DATA32	call	*%ax
+	calll	*%eax
 	.endm
 
 /*
diff --git a/grub-core/kern/i386/qemu/startup.S b/grub-core/kern/i386/qemu/startup.S
index 3d47d1e4f..0d89858d9 100644
--- a/grub-core/kern/i386/qemu/startup.S
+++ b/grub-core/kern/i386/qemu/startup.S
@@ -28,7 +28,7 @@
 _start:
 	jmp	codestart
 
-	. = _start + GRUB_KERNEL_I386_QEMU_CORE_ENTRY_ADDR
+	.org GRUB_KERNEL_I386_QEMU_CORE_ENTRY_ADDR
 VARIABLE(grub_core_entry_addr)
 	.long	0
 
@@ -73,5 +73,3 @@ codestart:
 1:	
 	hlt
 	jmp 1b
-
-#include "../realmode.S"
diff --git a/grub-core/kern/i386/realmode.S b/grub-core/kern/i386/realmode.S
index 541cedc87..998fdc756 100644
--- a/grub-core/kern/i386/realmode.S
+++ b/grub-core/kern/i386/realmode.S
@@ -54,7 +54,7 @@ protstack:
 	.endm
 
 	.macro REAL_TO_PROT
-	DATA32	call	real_to_prot
+	calll	real_to_prot
 	.endm
 
 /*
@@ -137,7 +137,22 @@ real_to_prot:
 	/* load the GDT register */
 	xorw	%ax, %ax
 	movw	%ax, %ds
-	DATA32	ADDR32	lgdt	gdtdesc
+#ifdef GRUB_MACHINE_QEMU
+	/*
+	qemu is special: gdtdesc is in ROM.
+	%cs = 0xf000
+	_start + GRUB_BOOT_MACHINE_SIZE = 0x100000
+	So
+	_start + GRUB_BOOT_MACHINE_SIZE - 0x10000 points to the same point
+	as %cs.
+	gdtdesc - (_start + GRUB_BOOT_MACHINE_SIZE - 0x10000)
+	= gdtdesc - _start - GRUB_BOOT_MACHINE_SIZE + 0x10000
+	but the later can be computed by assembly.
+	*/
+	lgdtl	%cs:(gdtdesc - _start - GRUB_BOOT_MACHINE_SIZE + 0x10000)
+#else
+	lgdtl	gdtdesc
+#endif
 
 	/* turn on protected mode */
 	movl	%cr0, %eax
@@ -145,7 +160,7 @@ real_to_prot:
 	movl	%eax, %cr0
 
 	/* jump to relocation, flush prefetch queue, and reload %cs */
-	DATA32	ljmp	$GRUB_MEMORY_MACHINE_PROT_MODE_CSEG, $protcseg
+	ljmpl	$GRUB_MEMORY_MACHINE_PROT_MODE_CSEG, $protcseg
 
 	.code32
 protcseg:
@@ -178,6 +193,9 @@ protcseg:
 
 	/* return on the old (or initialized) stack! */
 	ret
+	/* prot_to_real assumes that this code is under 64K which is not
+	true for qemu.  */
+#ifndef GRUB_MACHINE_QEMU
 /*
  *  GRUB  --  GRand Unified Bootloader
  *  Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2009,2010 Free Software Foundation, Inc.
@@ -237,7 +255,7 @@ tmpcseg:
 	movl	%eax, %cr0
 
 	/* flush prefetch queue, reload %cs */
-	DATA32	ljmp	$0, $realcseg
+	ljmpl	$0, $realcseg
 
 realcseg:
 	/* we are in real mode now
@@ -258,6 +276,6 @@ realcseg:
 #endif
 
 	/* return on new stack! */
-	DATA32	ret
-
+	retl
+#endif
 	.code32
diff --git a/grub-core/kern/i386/tsc.c b/grub-core/kern/i386/tsc.c
index 3a4cae601..bc441d0d3 100644
--- a/grub-core/kern/i386/tsc.c
+++ b/grub-core/kern/i386/tsc.c
@@ -57,6 +57,8 @@ grub_get_tsc (void)
   return (((grub_uint64_t) hi) << 32) | lo;
 }
 
+#ifndef GRUB_MACHINE_XEN
+
 static __inline int
 grub_cpu_is_tsc_supported (void)
 {
@@ -69,8 +71,6 @@ grub_cpu_is_tsc_supported (void)
   return (d & (1 << 4)) != 0;
 }
 
-#ifndef GRUB_MACHINE_XEN
-
 static void
 grub_pit_wait (grub_uint16_t tics)
 {
@@ -122,7 +122,11 @@ calibrate_tsc (void)
   grub_pit_wait (0xffff);
   end_tsc = grub_get_tsc ();
 
-  grub_tsc_rate = grub_divmod64 ((55ULL << 32), end_tsc - tsc_boot_time, 0);
+  grub_tsc_rate = 0;
+  if (end_tsc > tsc_boot_time)
+    grub_tsc_rate = grub_divmod64 ((55ULL << 32), end_tsc - tsc_boot_time, 0);
+  if (grub_tsc_rate == 0)
+    grub_tsc_rate = 5368;/* 800 MHz */
 }
 #endif
 
diff --git a/grub-core/kern/mips/cache.S b/grub-core/kern/mips/cache.S
index 78e40bcea..e83960fcc 100644
--- a/grub-core/kern/mips/cache.S
+++ b/grub-core/kern/mips/cache.S
@@ -1,8 +1,10 @@
 
 #include <grub/symbol.h>
+#include <grub/cpu/kernel.h>
 
 	.set noreorder
 	.set nomacro
+	mips_attributes
 
 FUNCTION (grub_arch_sync_caches)
 #include "cache_flush.S"
@@ -65,4 +67,4 @@ FUNCTION (grub_arch_sync_dma_caches)
 #endif
 	sync_op
 
-	jr $ra
\ No newline at end of file
+	jr $ra
diff --git a/grub-core/kern/mips/startup.S b/grub-core/kern/mips/startup.S
index 709a91afa..337aca914 100644
--- a/grub-core/kern/mips/startup.S
+++ b/grub-core/kern/mips/startup.S
@@ -21,6 +21,7 @@
 #include <grub/offsets.h>
 #include <grub/machine/memory.h>
 #include <grub/machine/kernel.h>
+#include <grub/cpu/kernel.h>
 #include <grub/offsets.h>
 
 #define BASE_ADDR 8	
@@ -28,6 +29,7 @@
 	.globl __start, _start, start
 	.set noreorder
 	.set nomacro
+	mips_attributes
 __start:
 _start:
 start:		
@@ -36,7 +38,7 @@ start:
 	bal cont
 	 nop
 
-	. = _start + GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE
+	.org GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE
 VARIABLE(grub_total_modules_size)
 	.long 0
 
diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
index c5c815d8d..906d2c2f7 100644
--- a/grub-core/kern/misc.c
+++ b/grub-core/kern/misc.c
@@ -95,25 +95,6 @@ grub_memmove (void *dest, const void *src, grub_size_t n)
   return dest;
 }
 
-#ifndef __APPLE__
-void *memmove (void *dest, const void *src, grub_size_t n)
-  __attribute__ ((alias ("grub_memmove")));
-/* GCC emits references to memcpy() for struct copies etc.  */
-void *memcpy (void *dest, const void *src, grub_size_t n)
-  __attribute__ ((alias ("grub_memmove")));
-#else
-void * GRUB_BUILTIN_ATTR
-memcpy (void *dest, const void *src, grub_size_t n)
-{
-	return grub_memmove (dest, src, n);
-}
-void * GRUB_BUILTIN_ATTR
-memmove (void *dest, const void *src, grub_size_t n)
-{
-	return grub_memmove (dest, src, n);
-}
-#endif
-
 char *
 grub_strcpy (char *dest, const char *src)
 {
@@ -253,16 +234,6 @@ grub_memcmp (const void *s1, const void *s2, grub_size_t n)
 
   return 0;
 }
-#ifndef __APPLE__
-int memcmp (const void *s1, const void *s2, grub_size_t n)
-  __attribute__ ((alias ("grub_memcmp")));
-#else
-int GRUB_BUILTIN_ATTR
-memcmp (const void *s1, const void *s2, grub_size_t n)
-{
-  return grub_memcmp (s1, s2, n);
-}
-#endif
 
 int
 grub_strcmp (const char *s1, const char *s2)
@@ -532,26 +503,6 @@ grub_memset (void *s, int c, grub_size_t len)
 
   return s;
 }
-#ifndef __APPLE__
-void *memset (void *s, int c, grub_size_t n)
-  __attribute__ ((alias ("grub_memset")));
-#else
-void * GRUB_BUILTIN_ATTR
-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)
-{
-  grub_memset (s, 0, n);
-}
-
-#endif
 
 grub_size_t
 grub_strlen (const char *s)
@@ -594,10 +545,10 @@ grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r)
   grub_uint64_t m = 0;
 
   /* ARM and IA64 don't have a fast 32-bit division.
-     Using that code would just make us use libgcc routines, calling
-     them twice (once for modulo and once for quotient.
+     Using that code would just make us use software division routines, calling
+     ourselves indirectly and hence getting infinite recursion.
   */
-#if !defined (__arm__) && !defined (__ia64__)
+#if !GRUB_DIVISION_IN_SOFTWARE
   /* Skip the slow computation if 32-bit arithmetic is possible.  */
   if (n < 0xffffffff && d < 0xffffffff)
     {
@@ -631,132 +582,6 @@ grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r)
   return q;
 }
 
-#if !defined (GRUB_UTIL) && !defined (GRUB_MACHINE_EMU)
-
-#if defined (__arm__)
-
-grub_uint32_t
-__udivsi3 (grub_uint32_t a, grub_uint32_t b)
-{
-  return grub_divmod64 (a, b, 0);
-}
-
-grub_uint32_t
-__umodsi3 (grub_uint32_t a, grub_uint32_t b)
-{
-  grub_uint64_t ret;
-  grub_divmod64 (a, b, &ret);
-  return ret;
-}
-
-#endif
-
-#ifdef NEED_CTZDI2
-
-unsigned
-__ctzdi2 (grub_uint64_t x)
-{
-  unsigned ret = 0;
-  if (!x)
-    return 64;
-  if (!(x & 0xffffffff))
-    {
-      x >>= 32;
-      ret |= 32;
-    }
-  if (!(x & 0xffff))
-    {
-      x >>= 16;
-      ret |= 16;
-    }
-  if (!(x & 0xff))
-    {
-      x >>= 8;
-      ret |= 8;
-    }
-  if (!(x & 0xf))
-    {
-      x >>= 4;
-      ret |= 4;
-    }
-  if (!(x & 0x3))
-    {
-      x >>= 2;
-      ret |= 2;
-    }
-  if (!(x & 0x1))
-    {
-      x >>= 1;
-      ret |= 1;
-    }
-  return ret;
-}
-#endif
-
-#ifdef NEED_CTZSI2
-unsigned
-__ctzsi2 (grub_uint32_t x)
-{
-  unsigned ret = 0;
-  if (!x)
-    return 32;
-
-  if (!(x & 0xffff))
-    {
-      x >>= 16;
-      ret |= 16;
-    }
-  if (!(x & 0xff))
-    {
-      x >>= 8;
-      ret |= 8;
-    }
-  if (!(x & 0xf))
-    {
-      x >>= 4;
-      ret |= 4;
-    }
-  if (!(x & 0x3))
-    {
-      x >>= 2;
-      ret |= 2;
-    }
-  if (!(x & 0x1))
-    {
-      x >>= 1;
-      ret |= 1;
-    }
-  return ret;
-}
-
-#endif
-
-#ifdef __arm__
-grub_uint32_t
-__aeabi_uidiv (grub_uint32_t a, grub_uint32_t b)
-  __attribute__ ((alias ("__udivsi3")));
-#endif
-
-#if defined (__ia64__)
-
-grub_uint64_t
-__udivdi3 (grub_uint64_t a, grub_uint64_t b)
-{
-  return grub_divmod64 (a, b, 0);
-}
-
-grub_uint64_t
-__umoddi3 (grub_uint64_t a, grub_uint64_t b)
-{
-  grub_uint64_t ret;
-  grub_divmod64 (a, b, &ret);
-  return ret;
-}
-
-#endif
-
-#endif /* GRUB_UTIL */
-
 /* Convert a long long value to a string. This function avoids 64-bit
    modular arithmetic or divisions.  */
 static inline char *
@@ -1265,15 +1090,6 @@ grub_abort (void)
   grub_exit ();
 }
 
-#if defined (__clang__) && !defined (GRUB_UTIL)
-/* clang emits references to abort().  */
-void __attribute__ ((noreturn))
-abort (void)
-{
-  grub_abort ();
-}
-#endif
-
 void
 grub_fatal (const char *fmt, ...)
 {
@@ -1286,23 +1102,6 @@ grub_fatal (const char *fmt, ...)
   grub_abort ();
 }
 
-#if (defined (__MINGW32__) || defined (__CYGWIN__)) && !defined(GRUB_UTIL)
-void __register_frame_info (void)
-{
-}
-
-void __deregister_frame_info (void)
-{
-}
-void ___chkstk_ms (void)
-{
-}
-
-void __chkstk_ms (void)
-{
-}
-#endif
-
 #if BOOT_TIME_STATS
 
 #include <grub/time.h>
diff --git a/grub-core/kern/powerpc/compiler-rt.S b/grub-core/kern/powerpc/compiler-rt.S
new file mode 100644
index 000000000..b3b912db6
--- /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
+ * <http://www.gnu.org/licenses/>.
+ */ 
+
+/* Do any initializations needed for the eabi environment */
+
+#include <grub/symbol.h>
+#include <grub/dl.h>
+
+	.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/grub-core/kern/sparc64/ieee1275/crt0.S b/grub-core/kern/sparc64/ieee1275/crt0.S
index 79b6bb325..03b916f05 100644
--- a/grub-core/kern/sparc64/ieee1275/crt0.S
+++ b/grub-core/kern/sparc64/ieee1275/crt0.S
@@ -27,7 +27,7 @@ _start:
 	ba	codestart
 	 mov  %o4, %o0
 
-	. = EXT_C(_start) + GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE
+	.org GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE
 
 VARIABLE(grub_total_module_size)
 	.word	0
diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c
index 8e8426c4a..010e550d1 100644
--- a/grub-core/lib/crypto.c
+++ b/grub-core/lib/crypto.c
@@ -205,13 +205,16 @@ grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher,
 {
   const grub_uint8_t *inptr, *end;
   grub_uint8_t *outptr;
+  grub_size_t blocksize;
   if (!cipher->cipher->decrypt)
     return GPG_ERR_NOT_SUPPORTED;
-  if (size % cipher->cipher->blocksize != 0)
+  blocksize = cipher->cipher->blocksize;
+  if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
+      || ((size & (blocksize - 1)) != 0))
     return GPG_ERR_INV_ARG;
   end = (const grub_uint8_t *) in + size;
   for (inptr = in, outptr = out; inptr < end;
-       inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
+       inptr += blocksize, outptr += blocksize)
     cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
   return GPG_ERR_NO_ERROR;
 }
@@ -222,13 +225,16 @@ grub_crypto_ecb_encrypt (grub_crypto_cipher_handle_t cipher,
 {
   const grub_uint8_t *inptr, *end;
   grub_uint8_t *outptr;
+  grub_size_t blocksize;
   if (!cipher->cipher->encrypt)
     return GPG_ERR_NOT_SUPPORTED;
-  if (size % cipher->cipher->blocksize != 0)
+  blocksize = cipher->cipher->blocksize;
+  if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
+      || ((size & (blocksize - 1)) != 0))
     return GPG_ERR_INV_ARG;
   end = (const grub_uint8_t *) in + size;
   for (inptr = in, outptr = out; inptr < end;
-       inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
+       inptr += blocksize, outptr += blocksize)
     cipher->cipher->encrypt (cipher->ctx, outptr, inptr);
   return GPG_ERR_NO_ERROR;
 }
@@ -241,20 +247,23 @@ grub_crypto_cbc_encrypt (grub_crypto_cipher_handle_t cipher,
   grub_uint8_t *outptr;
   const grub_uint8_t *inptr, *end;
   void *iv;
-  if (!cipher->cipher->decrypt)
+  grub_size_t blocksize;
+  if (!cipher->cipher->encrypt)
     return GPG_ERR_NOT_SUPPORTED;
-  if (size % cipher->cipher->blocksize != 0)
+  blocksize = cipher->cipher->blocksize;
+  if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
+      || ((size & (blocksize - 1)) != 0))
     return GPG_ERR_INV_ARG;
   end = (const grub_uint8_t *) in + size;
   iv = iv_in;
   for (inptr = in, outptr = out; inptr < end;
-       inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
+       inptr += blocksize, outptr += blocksize)
     {
-      grub_crypto_xor (outptr, inptr, iv, cipher->cipher->blocksize);
+      grub_crypto_xor (outptr, inptr, iv, blocksize);
       cipher->cipher->encrypt (cipher->ctx, outptr, outptr);
       iv = outptr;
     }
-  grub_memcpy (iv_in, iv, cipher->cipher->blocksize);
+  grub_memcpy (iv_in, iv, blocksize);
   return GPG_ERR_NO_ERROR;
 }
 
@@ -266,20 +275,23 @@ grub_crypto_cbc_decrypt (grub_crypto_cipher_handle_t cipher,
   const grub_uint8_t *inptr, *end;
   grub_uint8_t *outptr;
   grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE];
+  grub_size_t blocksize;
   if (!cipher->cipher->decrypt)
     return GPG_ERR_NOT_SUPPORTED;
-  if (size % cipher->cipher->blocksize != 0)
+  blocksize = cipher->cipher->blocksize;
+  if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
+      || ((size & (blocksize - 1)) != 0))
     return GPG_ERR_INV_ARG;
-  if (cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
+  if (blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
     return GPG_ERR_INV_ARG;
   end = (const grub_uint8_t *) in + size;
   for (inptr = in, outptr = out; inptr < end;
-       inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
+       inptr += blocksize, outptr += blocksize)
     {
-      grub_memcpy (ivt, inptr, cipher->cipher->blocksize);
+      grub_memcpy (ivt, inptr, blocksize);
       cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
-      grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize);
-      grub_memcpy (iv, ivt, cipher->cipher->blocksize);
+      grub_crypto_xor (outptr, outptr, iv, blocksize);
+      grub_memcpy (iv, ivt, blocksize);
     }
   return GPG_ERR_NO_ERROR;
 }
diff --git a/grub-core/lib/division.c b/grub-core/lib/division.c
new file mode 100644
index 000000000..35606fea7
--- /dev/null
+++ b/grub-core/lib/division.c
@@ -0,0 +1,74 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2015  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/misc.h>
+#include <grub/dl.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static grub_uint64_t
+abs64(grub_int64_t a)
+{
+  return a > 0 ? a : -a;
+}
+
+grub_int64_t
+grub_divmod64s (grub_int64_t n,
+		grub_int64_t d,
+		grub_int64_t *ro)
+{
+  grub_uint64_t ru;
+  grub_int64_t q, r;
+  q = grub_divmod64 (abs64(n), abs64(d), &ru);
+  r = ru;
+  /* Now: |n| = |d| * q + r  */
+  if (n < 0)
+    {
+      /* -|n| = |d| * (-q) + (-r)  */
+      q = -q;
+      r = -r;
+    }
+  /* Now: n = |d| * q + r  */
+  if (d < 0)
+    {
+      /* n = (-|d|) * (-q) + r  */
+      q = -q;
+    }
+  /* Now: n = d * q + r  */
+  if (ro)
+    *ro = r;
+  return q;
+}
+
+grub_uint32_t
+grub_divmod32 (grub_uint32_t n, grub_uint32_t d, grub_uint32_t *ro)
+{
+  grub_uint64_t q, r;
+  q = grub_divmod64 (n, d, &r);
+  *ro = r;
+  return q;
+}
+
+grub_int32_t
+grub_divmod32s (grub_int32_t n, grub_int32_t d, grub_int32_t *ro)
+{
+  grub_int64_t q, r;
+  q = grub_divmod64s (n, d, &r);
+  *ro = r;
+  return q;
+}
diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c
index 61266d95a..ef56150ac 100644
--- a/grub-core/lib/legacy_parse.c
+++ b/grub-core/lib/legacy_parse.c
@@ -664,6 +664,7 @@ grub_legacy_parse (const char *buf, char **entryname, char **suffix)
 	  {
 	  case TYPE_FILE_NO_CONSUME:
 	    hold_arg = 1;
+	    /* Fallthrough.  */
 	  case TYPE_PARTITION:
 	  case TYPE_FILE:
 	    args[i] = adjust_file (curarg, curarglen);
diff --git a/grub-core/lib/mips/relocator_asm.S b/grub-core/lib/mips/relocator_asm.S
index 1d142a4f3..959893ca9 100644
--- a/grub-core/lib/mips/relocator_asm.S
+++ b/grub-core/lib/mips/relocator_asm.S
@@ -17,11 +17,13 @@
  */
 
 #include <grub/symbol.h>
+#include <grub/cpu/kernel.h>
 	
 	.p2align	4	/* force 16-byte alignment */
 
 	.set noreorder
 	.set nomacro
+	mips_attributes
 
 VARIABLE (grub_relocator_forward_start)
 	move $a0, $9
diff --git a/grub-core/lib/pbkdf2.c b/grub-core/lib/pbkdf2.c
index 2fbaa95e8..01cee3951 100644
--- a/grub-core/lib/pbkdf2.c
+++ b/grub-core/lib/pbkdf2.c
@@ -52,7 +52,7 @@ grub_crypto_pbkdf2 (const struct gcry_md_spec *md,
   grub_uint8_t *tmp;
   grub_size_t tmplen = Slen + 4;
 
-  if (md->mdlen > GRUB_CRYPTO_MAX_MDLEN)
+  if (md->mdlen > GRUB_CRYPTO_MAX_MDLEN || md->mdlen == 0)
     return GPG_ERR_INV_ARG;
 
   if (c == 0)
diff --git a/grub-core/lib/posix_wrap/string.h b/grub-core/lib/posix_wrap/string.h
index c4b9bf089..7ae6eee97 100644
--- a/grub-core/lib/posix_wrap/string.h
+++ b/grub-core/lib/posix_wrap/string.h
@@ -42,21 +42,6 @@ strcasecmp (const char *s1, const char *s2)
   return grub_strcasecmp (s1, s2);
 }
 
-#ifdef GRUB_UTIL
-static inline void *
-memcpy (void *dest, const void *src, grub_size_t n)
-{
-  return grub_memcpy (dest, src, n);
-}
-
-static inline int
-memcmp (const void *s1, const void *s2, grub_size_t n)
-{
-  return grub_memcmp (s1, s2, n);
-}
-
-#endif
-
 static inline void
 bcopy (const void *src, void *dest, grub_size_t n)
 {
@@ -99,4 +84,9 @@ memchr (const void *s, int c, grub_size_t n)
   return grub_memchr (s, c, n);
 }
 
+#define memcmp grub_memcmp
+#define memcpy grub_memcpy
+#define memmove grub_memmove
+#define memset grub_memset
+
 #endif
diff --git a/grub-core/lib/syslinux_parse.c b/grub-core/lib/syslinux_parse.c
index 6bc504b7c..153260b54 100644
--- a/grub-core/lib/syslinux_parse.c
+++ b/grub-core/lib/syslinux_parse.c
@@ -649,6 +649,8 @@ helptext (const char *line, grub_file_t file, struct syslinux_menu *menu)
   grub_size_t helplen, alloclen = 0;
 
   help = grub_strdup (line);
+  if (!help)
+    return grub_errno;
   helplen = grub_strlen (line);
   while ((grub_free (buf), buf = grub_file_getline (file)))
     {
@@ -682,6 +684,7 @@ helptext (const char *line, grub_file_t file, struct syslinux_menu *menu)
     }
 
   grub_free (buf);
+  grub_free (help);
   return grub_errno;
 }
 
@@ -717,7 +720,7 @@ syslinux_parse_real (struct syslinux_menu *menu)
       for (ptr3 = ptr2;  grub_isspace (*ptr3) && *ptr3; ptr3++);
       for (ptr4 = ptr3; !grub_isspace (*ptr4) && *ptr4; ptr4++);
       for (ptr5 = ptr4;  grub_isspace (*ptr5) && *ptr5; ptr5++);
-      for (i = 0; i < sizeof (commands) / sizeof (commands[0]); i++)
+      for (i = 0; i < ARRAY_SIZE(commands); i++)
 	if (grub_strlen (commands[i].name1) == (grub_size_t) (ptr2 - ptr1)
 	    && grub_strncasecmp (commands[i].name1, ptr1, ptr2 - ptr1) == 0
 	    && (commands[i].name2 == NULL
@@ -726,7 +729,7 @@ syslinux_parse_real (struct syslinux_menu *menu)
 		    && grub_strncasecmp (commands[i].name2, ptr3, ptr4 - ptr3)
 		    == 0)))
 	  break;
-      if (i == sizeof (commands) / sizeof (commands[0]))
+      if (i == ARRAY_SIZE(commands))
 	{
 	  if (sizeof ("text") - 1 == ptr2 - ptr1
 	      && grub_strncasecmp ("text", ptr1, ptr2 - ptr1) == 0
@@ -836,6 +839,82 @@ simplify_filename (char *str)
   *optr = '\0';
 }
 
+static grub_err_t
+print_config (struct output_buffer *outbuf,
+	      struct syslinux_menu *menu,
+              const char *filename, const char *basedir)
+{
+  struct syslinux_menu *menuptr;
+  grub_err_t err = GRUB_ERR_NONE;
+  char *new_cwd = NULL;
+  char *new_target_cwd = NULL;
+  char *newname = NULL;
+  int depth = 0;
+
+  new_cwd = get_read_filename (menu, basedir);
+  if (!new_cwd)
+    {
+      err = grub_errno;
+      goto out;
+    }
+  new_target_cwd = get_target_filename (menu, basedir);
+  if (!new_target_cwd)
+    {
+      err = grub_errno;
+      goto out;
+    }
+  newname = get_read_filename (menu, filename);
+  if (!newname)
+    {
+      err = grub_errno;
+      goto out;
+    }
+  simplify_filename (newname);
+
+  print_string ("#");
+  print_file (outbuf, menu, filename, NULL);
+  print_string (" ");
+  print (outbuf, newname, grub_strlen (newname));
+  print_string (":\n");
+
+  for (menuptr = menu; menuptr; menuptr = menuptr->parent, depth++)
+    if (grub_strcmp (menuptr->filename, newname) == 0
+        || depth > 20)
+      break;
+  if (menuptr)
+    {
+      print_string ("  syslinux_configfile -r ");
+      print_file (outbuf, menu, "/", NULL);
+      print_string (" -c ");
+      print_file (outbuf, menu, basedir, NULL);
+      print_string (" ");
+      print_file (outbuf, menu, filename, NULL);
+      print_string ("\n");
+    }
+  else
+    {
+      err = config_file (outbuf, menu->root_read_directory,
+                         menu->root_target_directory, new_cwd, new_target_cwd,
+                         newname, menu, menu->flavour);
+      if (err == GRUB_ERR_FILE_NOT_FOUND
+          || err == GRUB_ERR_BAD_FILENAME)
+        {
+          grub_errno = err = GRUB_ERR_NONE;
+          print_string ("# File ");
+          err = print (outbuf, newname, grub_strlen (newname));
+          if (err)
+            goto out;
+          print_string (" not found\n");
+        }
+    }
+
+ out:
+  grub_free (newname);
+  grub_free (new_cwd);
+  grub_free (new_target_cwd);
+  return err;
+}
+
 static grub_err_t
 write_entry (struct output_buffer *outbuf,
 	     struct syslinux_menu *menu,
@@ -843,7 +922,12 @@ write_entry (struct output_buffer *outbuf,
 {
   grub_err_t err;
   if (curentry->comments)
-    print (outbuf, curentry->comments, grub_strlen (curentry->comments));
+    {
+      err = print (outbuf, curentry->comments,
+		   grub_strlen (curentry->comments));
+      if (err)
+	return err;
+    }
   {
     struct syslinux_say *say;
     for (say = curentry->say; say && say->next; say = say->next);
@@ -861,7 +945,6 @@ write_entry (struct output_buffer *outbuf,
     case KERNEL_LINUX:
       {
 	char *ptr;
-	char *cmdline;
 	char *initrd = NULL;
 	for (ptr = curentry->append; ptr && *ptr; ptr++)
 	  if ((ptr == curentry->append || grub_isspace (ptr[-1]))
@@ -871,31 +954,19 @@ write_entry (struct output_buffer *outbuf,
 	if (ptr && *ptr)
 	  {
 	    char *ptr2;
-	    grub_size_t totlen = grub_strlen (curentry->append);
-	    initrd = ptr + sizeof ("initrd=") - 1;
-	    for (ptr2 = ptr; *ptr2 && !grub_isspace (*ptr2); ptr2++);
-	    if (*ptr2)
-	      {
-		*ptr2 = 0;
-		ptr2++;
-	      }
-	    cmdline = grub_malloc (totlen + 1 - (ptr2 - ptr));
-	    if (!cmdline)
+	    initrd = grub_strdup(ptr + sizeof ("initrd=") - 1);
+	    if (!initrd)
 	      return grub_errno;
-	    grub_memcpy (cmdline, curentry->append, ptr - curentry->append);
-	    grub_memcpy (cmdline + (ptr - curentry->append),
-			 ptr2, totlen - (ptr2 - curentry->append));
-	    *(cmdline + totlen - (ptr2 - ptr)) = 0;
+	    for (ptr2 = initrd; *ptr2 && !grub_isspace (*ptr2); ptr2++);
+	    *ptr2 = 0;
 	  }
-	else
-	  cmdline = curentry->append;
 	print_string (" if test x$grub_platform = xpc; then "
 		      "linux_suffix=16; else linux_suffix= ; fi\n");
 	print_string ("  linux$linux_suffix ");
 	print_file (outbuf, menu, curentry->kernel_file, NULL);
 	print_string (" ");
-	if (cmdline)
-	  print (outbuf, cmdline, grub_strlen (cmdline));
+	if (curentry->append)
+	  print (outbuf, curentry->append, grub_strlen (curentry->append));
 	print_string ("\n");
 	if (initrd || curentry->initrds)
 	  {
@@ -914,6 +985,7 @@ write_entry (struct output_buffer *outbuf,
 
 	    print_string ("\n");
 	  }
+	grub_free (initrd);
       }
       break;
     case KERNEL_CHAINLOADER:
@@ -949,6 +1021,7 @@ write_entry (struct output_buffer *outbuf,
 	    break;
 	  }
 	print_string ("  # UNSUPPORTED localboot type ");
+	print_string ("\ntrue;\n");
 	if (print_num (outbuf, n))
 	  return grub_errno;
 	print_string ("\n");
@@ -1230,6 +1303,36 @@ write_entry (struct output_buffer *outbuf,
 	    break;
 	  }
 
+	if (grub_strcasecmp (basename, "menu.c32") == 0 ||
+	    grub_strcasecmp (basename, "vesamenu.c32") == 0)
+	  {
+	    char *ptr;
+	    char *end;
+
+	    ptr = curentry->append;
+	    if (!ptr)
+	      return grub_errno;
+
+	    while (*ptr)
+	      {
+		end = ptr;
+		for (end = ptr; *end && !grub_isspace (*end); end++);
+		if (*end)
+		  *end++ = '\0';
+
+		/* "~" is supposed to be current file, so let's skip it */
+		if (grub_strcmp (ptr, "~") != 0)
+		  {
+		    err = print_config (outbuf, menu, ptr, "");
+		    if (err != GRUB_ERR_NONE)
+		      break;
+                  }
+		for (ptr = end; *ptr && grub_isspace (*ptr); ptr++);
+	      }
+	    err = GRUB_ERR_NONE;
+	    break;
+	  }
+
 	/* FIXME: gdb, GFXBoot, Hdt, Ifcpu, Ifplop, Kbdmap,
 	   FIXME: Linux, Lua, Meminfo, rosh, Sanbboot  */
 
@@ -1242,70 +1345,13 @@ write_entry (struct output_buffer *outbuf,
       }
     case KERNEL_CONFIG:
       {
-	char *new_cwd, *new_target_cwd;
 	const char *ap;
 	ap = curentry->append;
 	if (!ap)
 	  ap = curentry->argument;
 	if (!ap)
 	  ap = "";
-	new_cwd = get_read_filename (menu, ap);
-	if (!new_cwd)
-	  return grub_errno;
-	new_target_cwd = get_target_filename (menu, ap);
-	if (!new_target_cwd)
-	  return grub_errno;
-
-	struct syslinux_menu *menuptr;
-	char *newname;
-	int depth = 0;
-	
-	newname = get_read_filename (menu, curentry->kernel_file);
-	if (!newname)
-	  return grub_errno;
-	simplify_filename (newname);
-
-	print_string ("#");
-	print_file (outbuf, menu, curentry->kernel_file, NULL);
-	print_string (" ");
-	print (outbuf, newname, grub_strlen (newname));
-	print_string (":\n");
-
-	for (menuptr = menu; menuptr; menuptr = menuptr->parent, depth++)
-	  if (grub_strcmp (menuptr->filename, newname) == 0
-	      || depth > 20)
-	    break;
-	if (menuptr)
-	  {
-	    print_string ("  syslinux_configfile -r ");
-	    print_file (outbuf, menu, "/", NULL);
-	    print_string (" -c ");
-	    print_file (outbuf, menu, ap, NULL);
-	    print_string (" ");
-	    print_file (outbuf, menu, curentry->kernel_file, NULL);
-	    print_string ("\n");
-	  }
-	else
-	  {
-	    err = config_file (outbuf, menu->root_read_directory,
-			       menu->root_target_directory, new_cwd, new_target_cwd,
-			       newname, menu, menu->flavour);
-	    if (err == GRUB_ERR_FILE_NOT_FOUND
-		|| err == GRUB_ERR_BAD_FILENAME)
-	      {
-		grub_errno = err = GRUB_ERR_NONE;
-		print_string ("# File ");
-		err = print (outbuf, newname, grub_strlen (newname));
-		if (err)
-		  return err;
-		print_string (" not found\n");
-	      }
-	    if (err)
-	      return err;
-	  }
-	grub_free (newname);
-	grub_free (new_cwd);
-	grub_free (new_target_cwd);
+	print_config (outbuf, menu, curentry->kernel_file, ap);
       }
       break;
     case KERNEL_NO_KERNEL:
@@ -1351,7 +1397,6 @@ free_menu (struct syslinux_menu *menu)
   for (say = menu->say; say ; say = nsay)
     {
       nsay = say->next;
-      grub_free (say->msg);
       grub_free (say);
     }
 
@@ -1421,6 +1466,13 @@ config_file (struct output_buffer *outbuf,
       print_string ("\n");
     }
 
+  if (menu.comments)
+    {
+      err = print (outbuf, menu.comments, grub_strlen (menu.comments));
+      if (err)
+	return err;
+    }
+
   if (menu.timeout == 0 && menu.entries && menu.def)
     {
       err = print_entry (outbuf, &menu, menu.def);
@@ -1437,12 +1489,6 @@ config_file (struct output_buffer *outbuf,
       if (err)
 	return err;
       print_string ("\n");
-      if (menu.comments)
-	{
-	  err = print (outbuf, menu.comments, grub_strlen (menu.comments));
-	  if (err)
-	    return err;
-	}
 
       if (menu.def)
 	{
diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c
index 8f691e0e2..bc377b362 100644
--- a/grub-core/loader/i386/bsd.c
+++ b/grub-core/loader/i386/bsd.c
@@ -234,7 +234,8 @@ grub_bsd_add_meta_ptr (grub_uint32_t type, void **ptr, grub_uint32_t len)
     {
       struct bsd_tag *p;
       for (p = tags;
-	   p->type != (FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_KERNEND);
+	   p && p->type != (FREEBSD_MODINFO_METADATA
+			    | FREEBSD_MODINFOMD_KERNEND);
 	   p = p->next);
 
       if (p)
diff --git a/grub-core/loader/i386/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c
index f10c087f7..956d0e37b 100644
--- a/grub-core/loader/i386/multiboot_mbi.c
+++ b/grub-core/loader/i386/multiboot_mbi.c
@@ -121,6 +121,24 @@ load_kernel (grub_file_t file, const char *filename,
   return grub_multiboot_load_elf (file, filename, buffer);
 }
 
+static struct multiboot_header *
+find_header (char *buffer, grub_ssize_t len)
+{
+  struct multiboot_header *header;
+
+  /* Look for the multiboot header in the buffer.  The header should
+     be at least 12 bytes and aligned on a 4-byte boundary.  */
+  for (header = (struct multiboot_header *) buffer;
+       ((char *) header <= buffer + len - 12);
+       header = (struct multiboot_header *) ((char *) header + MULTIBOOT_HEADER_ALIGN))
+    {
+      if (header->magic == MULTIBOOT_HEADER_MAGIC
+	  && !(header->magic + header->flags + header->checksum))
+	return header;
+    }
+  return NULL;
+}
+
 grub_err_t
 grub_multiboot_load (grub_file_t file, const char *filename)
 {
@@ -143,16 +161,7 @@ grub_multiboot_load (grub_file_t file, const char *filename)
       return grub_errno;
     }
 
-  /* Look for the multiboot header in the buffer.  The header should
-     be at least 12 bytes and aligned on a 4-byte boundary.  */
-  for (header = (struct multiboot_header *) buffer;
-       ((char *) header <= buffer + len - 12) || (header = 0);
-       header = (struct multiboot_header *) ((char *) header + MULTIBOOT_HEADER_ALIGN))
-    {
-      if (header->magic == MULTIBOOT_HEADER_MAGIC
-	  && !(header->magic + header->flags + header->checksum))
-	break;
-    }
+  header = find_header (buffer, len);
 
   if (header == 0)
     {
diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
index 870992b7d..a293b17aa 100644
--- a/grub-core/loader/i386/pc/linux.c
+++ b/grub-core/loader/i386/pc/linux.c
@@ -280,10 +280,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 	      {
 	      case 'g':
 		shift += 10;
+		/* Fallthrough.  */
 	      case 'm':
 		shift += 10;
+		/* Fallthrough.  */
 	      case 'k':
 		shift += 10;
+		/* Fallthrough.  */
 	      default:
 		break;
 	      }
diff --git a/grub-core/loader/i386/pc/plan9.c b/grub-core/loader/i386/pc/plan9.c
index 0d10b1c24..814a49d50 100644
--- a/grub-core/loader/i386/pc/plan9.c
+++ b/grub-core/loader/i386/pc/plan9.c
@@ -342,6 +342,7 @@ fill_disk (const char *name, void *data)
   if (!plan9name)
     {
       grub_print_error ();
+      grub_device_close (dev);
       return 0;
     }
   if (grub_extend_alloc (fill_ctx->pmapptr + grub_strlen (plan9name)
@@ -349,6 +350,7 @@ fill_disk (const char *name, void *data)
 			 &fill_ctx->pmap))
     {
       grub_free (plan9name);
+      grub_device_close (dev);
       return 1;
     }
   grub_strcpy (fill_ctx->pmap + fill_ctx->pmapptr, plan9name);
@@ -366,12 +368,19 @@ fill_disk (const char *name, void *data)
   fill_ctx->noslash = 1;
   grub_memset (fill_ctx->prefixescnt, 0, sizeof (fill_ctx->prefixescnt));
   if (grub_partition_iterate (dev->disk, fill_partition, fill_ctx))
-    return 1;
+    {
+      grub_device_close (dev);
+      return 1;
+    }
   if (grub_extend_alloc (fill_ctx->pmapptr + 1, &fill_ctx->pmapalloc,
 			 &fill_ctx->pmap))
-    return 1;
+    {
+      grub_device_close (dev);
+      return 1;
+    }
   fill_ctx->pmap[fill_ctx->pmapptr++] = '\n';
 
+  grub_device_close (dev);
   return 0;
 }
 
diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c
index c16b4b249..c4d9689f7 100644
--- a/grub-core/loader/i386/xen.c
+++ b/grub-core/loader/i386/xen.c
@@ -521,7 +521,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
 {
   grub_size_t size = 0;
   grub_err_t err;
-  struct grub_linux_initrd_context initrd_ctx;
+  struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 };
   grub_relocator_chunk_t ch;
 
   if (argc == 0)
diff --git a/grub-core/loader/i386/xen_fileXX.c b/grub-core/loader/i386/xen_fileXX.c
index 73a5f90fd..1ba5649e2 100644
--- a/grub-core/loader/i386/xen_fileXX.c
+++ b/grub-core/loader/i386/xen_fileXX.c
@@ -311,14 +311,19 @@ grub_xen_get_infoXX (grub_elf_t elf, struct grub_xen_file_info *xi)
     return grub_errno;
 
   if (grub_file_seek (elf->file, elf->ehdr.ehdrXX.e_shoff) == (grub_off_t) -1)
-    return grub_errno;
+    {
+      err = grub_errno;
+      goto cleanup;
+    }
 
   if (grub_file_read (elf->file, s0, shsize) != (grub_ssize_t) shsize)
     {
       if (grub_errno)
-	return grub_errno;
-      return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+	err = grub_errno;
+      else
+	err = grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
 			 elf->file->name);
+      goto cleanup;
     }
 
   s = (Elf_Shdr *) ((char *) s0 + elf->ehdr.ehdrXX.e_shstrndx * shentsize);
@@ -330,18 +335,29 @@ grub_xen_get_infoXX (grub_elf_t elf, struct grub_xen_file_info *xi)
       char name[sizeof("__xen_guest")];
       grub_memset (name, 0, sizeof (name));
       if (grub_file_seek (elf->file, stroff + s->sh_name) == (grub_off_t) -1)
-	return grub_errno;
+	{
+	  err = grub_errno;
+	  goto cleanup;
+	}
 
       if (grub_file_read (elf->file, name, sizeof (name)) != (grub_ssize_t) sizeof (name))
 	{
 	  if (grub_errno)
-	    return grub_errno;
+	    {
+	      err = grub_errno;
+	      goto cleanup;
+	    }
 	  continue;
 	}
       if (grub_memcmp (name, "__xen_guest",
 		       sizeof("__xen_guest")) != 0)
 	continue;
-      return parse_xen_guest (elf, xi, s->sh_offset, s->sh_size);
+      err = parse_xen_guest (elf, xi, s->sh_offset, s->sh_size);
+      goto cleanup;
     }
-  return grub_error (GRUB_ERR_BAD_OS, "no XEN note found");
+  err = grub_error (GRUB_ERR_BAD_OS, "no XEN note found");
+
+cleanup:
+  grub_free (s0);
+  return err;
 }
diff --git a/grub-core/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c
index e83e1e972..e0506a676 100644
--- a/grub-core/loader/i386/xnu.c
+++ b/grub-core/loader/i386/xnu.c
@@ -126,7 +126,7 @@ guessfsb (void)
 {
   const grub_uint64_t sane_value = 100000000;
   grub_uint32_t manufacturer[3], max_cpuid, capabilities, msrlow;
-  grub_uint32_t a, b, d;
+  grub_uint32_t a, b, d, divisor;
 
   if (! grub_cpu_is_cpuid_supported ())
     return sane_value;
@@ -166,8 +166,10 @@ guessfsb (void)
   r = (2000ULL << 32) - v * grub_tsc_rate;
   v += r / grub_tsc_rate;
 
-  return grub_divmod64 (v, ((msrlow >> 7) & 0x3e) | ((msrlow >> 14) & 1),
-			 0);
+  divisor = ((msrlow >> 7) & 0x3e) | ((msrlow >> 14) & 1);
+  if (divisor == 0)
+    return sane_value;
+  return grub_divmod64 (v, divisor, 0);
 }
 
 struct property_descriptor
@@ -741,10 +743,10 @@ grub_cpu_xnu_fill_devicetree (grub_uint64_t *fsbfreq_out)
 	*((grub_uint64_t *) curval->data) = (grub_addr_t) ptr;
 
       /* Create alias. */
-      for (j = 0; j < sizeof (table_aliases) / sizeof (table_aliases[0]); j++)
+      for (j = 0; j < ARRAY_SIZE(table_aliases); j++)
 	if (grub_memcmp (&table_aliases[j].guid, &guid, sizeof (guid)) == 0)
 	  break;
-      if (j != sizeof (table_aliases) / sizeof (table_aliases[0]))
+      if (j != ARRAY_SIZE(table_aliases))
 	{
 	  curval = grub_xnu_create_value (&(curkey->first_child), "alias");
 	  if (!curval)
diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c
index 83e8919fa..d7c19bc99 100644
--- a/grub-core/loader/multiboot_mbi2.c
+++ b/grub-core/loader/multiboot_mbi2.c
@@ -79,6 +79,25 @@ grub_multiboot_add_elfsyms (grub_size_t num, grub_size_t entsize,
   elf_sections = data;
 }
 
+static struct multiboot_header *
+find_header (grub_properly_aligned_t *buffer, grub_ssize_t len)
+{
+  struct multiboot_header *header;
+  /* Look for the multiboot header in the buffer.  The header should
+     be at least 12 bytes and aligned on a 4-byte boundary.  */
+  for (header = (struct multiboot_header *) buffer;
+       ((char *) header <= (char *) buffer + len - 12);
+       header = (struct multiboot_header *) ((grub_uint32_t *) header + MULTIBOOT_HEADER_ALIGN / 4))
+    {
+      if (header->magic == MULTIBOOT_HEADER_MAGIC
+	  && !(header->magic + header->architecture
+	       + header->header_length + header->checksum)
+	  && header->architecture == MULTIBOOT_ARCHITECTURE_CURRENT)
+	return header;
+    }
+  return NULL;
+}
+
 grub_err_t
 grub_multiboot_load (grub_file_t file, const char *filename)
 {
@@ -107,18 +126,7 @@ grub_multiboot_load (grub_file_t file, const char *filename)
 
   COMPILE_TIME_ASSERT (MULTIBOOT_HEADER_ALIGN % 4 == 0);
 
-  /* Look for the multiboot header in the buffer.  The header should
-     be at least 12 bytes and aligned on a 4-byte boundary.  */
-  for (header = (struct multiboot_header *) buffer;
-       ((char *) header <= (char *) buffer + len - 12) || (header = 0);
-       header = (struct multiboot_header *) ((grub_uint32_t *) header + MULTIBOOT_HEADER_ALIGN / 4))
-    {
-      if (header->magic == MULTIBOOT_HEADER_MAGIC
-	  && !(header->magic + header->architecture
-	       + header->header_length + header->checksum)
-	  && header->architecture == MULTIBOOT_ARCHITECTURE_CURRENT)
-	break;
-    }
+  header = find_header (buffer, len);
 
   if (header == 0)
     {
@@ -142,7 +150,7 @@ grub_multiboot_load (grub_file_t file, const char *filename)
 	    = (struct multiboot_header_tag_information_request *) tag;
 	  if (request_tag->flags & MULTIBOOT_HEADER_TAG_OPTIONAL)
 	    break;
-	  for (i = 0; i < (request_tag->size - sizeof (request_tag))
+	  for (i = 0; i < (request_tag->size - sizeof (*request_tag))
 		 / sizeof (request_tag->requests[0]); i++)
 	    switch (request_tag->requests[i])
 	      {
diff --git a/grub-core/loader/sparc64/ieee1275/linux.c b/grub-core/loader/sparc64/ieee1275/linux.c
index 6389170e6..63d6a1f33 100644
--- a/grub-core/loader/sparc64/ieee1275/linux.c
+++ b/grub-core/loader/sparc64/ieee1275/linux.c
@@ -110,7 +110,7 @@ grub_linux_boot (void)
       int len = grub_strlen (linux_args) + 1;
       if (bp->len < len)
 	len = bp->len;
-      memcpy(bp->buf, linux_args, len);
+      grub_memcpy(bp->buf, linux_args, len);
       bp->buf[len-1] = '\0';
       bp->valid = 1;
     }
diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c
index cdd9715ce..c9885b1bc 100644
--- a/grub-core/loader/xnu.c
+++ b/grub-core/loader/xnu.c
@@ -689,10 +689,10 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile,
   /* Allocate the space. */
   err = grub_xnu_align_heap (GRUB_XNU_PAGESIZE);
   if (err)
-    return err;
+    goto fail;
   err = grub_xnu_heap_malloc (neededspace, &buf0, &buf_target);
   if (err)
-    return err;
+    goto fail;
   buf = buf0;
 
   exthead = (struct grub_xnu_extheader *) buf;
@@ -709,10 +709,7 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile,
       else
 	err = grub_macho_readfile32 (macho, filename, buf);
       if (err)
-	{
-	  grub_macho_close (macho);
-	  return err;
-	}
+	goto fail;
       grub_macho_close (macho);
       buf += machosize;
     }
@@ -747,6 +744,10 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile,
   /* Announce to kernel */
   return grub_xnu_register_memory ("Driver-", &driversnum, buf_target,
 				   neededspace);
+fail:
+  if (macho)
+    grub_macho_close (macho);
+  return err;
 }
 
 /* Load mkext. */
@@ -1378,6 +1379,8 @@ grub_xnu_fill_devicetree (void)
     name[len] = 0;
 
     curvalue = grub_xnu_create_value (curkey, name);
+    if (!curvalue)
+      return grub_errno;
     grub_free (name);
    
     data = grub_malloc (grub_strlen (var->value) + 1);
diff --git a/grub-core/modinfo.sh.in b/grub-core/modinfo.sh.in
index 69d833432..faf0ad30e 100644
--- a/grub-core/modinfo.sh.in
+++ b/grub-core/modinfo.sh.in
@@ -9,8 +9,6 @@ grub_have_font_source=@HAVE_FONT_SOURCE@
 
 # Autodetected config
 grub_have_asm_uscore=@HAVE_ASM_USCORE@
-grub_i8086_addr32="@ADDR32@"
-grub_i8086_data32="@DATA32@"
 grub_bss_start_symbol="@BSS_START_SYMBOL@"
 grub_end_symbol="@END_SYMBOL@"
 
@@ -21,11 +19,17 @@ grub_target_cflags='@TARGET_CFLAGS@'
 grub_target_cppflags='@TARGET_CPPFLAGS@'
 grub_target_ccasflags='@TARGET_CCASFLAGS@'
 grub_target_ldflags='@TARGET_LDFLAGS@'
+grub_cflags='@CFLAGS@'
+grub_cppflags='@CPPFLAGS@'
+grub_ccasflags='@CCASFLAGS@'
+grub_ldflags='@LDFLAGS@'
 grub_target_strip='@TARGET_STRIP@'
 grub_target_nm='@TARGET_NM@'
 grub_target_ranlib='@TARGET_RANLIB@'
 grub_target_objconf='@TARGET_OBJCONV@'
 grub_target_obj2elf='@TARGET_OBJ2ELF@'
+grub_target_img_base_ldopt='@TARGET_IMG_BASE_LDOPT@'
+grub_target_img_ldflags='@TARGET_IMG_BASE_LDFLAGS@'
 
 # Version
 grub_version="@VERSION@"
diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c
index 8cc390b0e..4b68c4151 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,26 @@ 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_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);
-
-  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 +104,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 +114,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/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
index 2b344d6ef..f171f20bf 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/grub-core/net/drivers/emu/emunet.c b/grub-core/net/drivers/emu/emunet.c
index 7c977cd52..b19492086 100644
--- a/grub-core/net/drivers/emu/emunet.c
+++ b/grub-core/net/drivers/emu/emunet.c
@@ -98,7 +98,7 @@ static int registered = 0;
 
 GRUB_MOD_INIT(emunet)
 {
-  if (grub_emunet_create (&emucard.mtu))
+  if (!grub_emunet_create (&emucard.mtu))
     {
       grub_net_card_register (&emucard);
       registered = 1;
diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c
index e8c0b22e2..3f4152d03 100644
--- a/grub-core/net/drivers/i386/pc/pxe.c
+++ b/grub-core/net/drivers/i386/pc/pxe.c
@@ -218,8 +218,7 @@ grub_pxe_recv (struct grub_net_card *dev __attribute__ ((unused)))
     return NULL;
   /* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible
      by 4. So that IP header is aligned on 4 bytes. */
-  grub_netbuff_reserve (buf, 2);
-  if (!buf)
+  if (grub_netbuff_reserve (buf, 2))
     {
       grub_netbuff_free (buf);
       return NULL;
diff --git a/grub-core/net/icmp.c b/grub-core/net/icmp.c
index 28d825ba0..b1eef114e 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/icmp6.c b/grub-core/net/icmp6.c
index 796d549f6..7953e68ec 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_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)
+    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/ip.c b/grub-core/net/ip.c
index 5a6095444..8c56baaf7 100644
--- a/grub-core/net/ip.c
+++ b/grub-core/net/ip.c
@@ -191,15 +191,18 @@ grub_net_send_ip4_packet (struct grub_net_network_level_interface *inf,
 			  grub_net_ip_protocol_t proto)
 {
   struct iphdr *iph;
+  grub_err_t err;
 
   COMPILE_TIME_ASSERT (GRUB_NET_OUR_IPV4_HEADER_SIZE == sizeof (*iph));
 
   if (nb->tail - nb->data + sizeof (struct iphdr) > inf->card->mtu)
     return send_fragmented (inf, target, nb, proto, *ll_target_addr);
 
-  grub_netbuff_push (nb, sizeof (*iph));
-  iph = (struct iphdr *) nb->data;
+  err = grub_netbuff_push (nb, sizeof (*iph));
+  if (err)
+    return err;
 
+  iph = (struct iphdr *) nb->data;
   iph->verhdrlen = ((4 << 4) | 5);
   iph->service = 0;
   iph->len = grub_cpu_to_be16 (nb->tail - nb->data);
@@ -602,15 +605,18 @@ grub_net_send_ip6_packet (struct grub_net_network_level_interface *inf,
 			  grub_net_ip_protocol_t proto)
 {
   struct ip6hdr *iph;
+  grub_err_t err;
 
   COMPILE_TIME_ASSERT (GRUB_NET_OUR_IPV6_HEADER_SIZE == sizeof (*iph));
 
   if (nb->tail - nb->data + sizeof (struct iphdr) > inf->card->mtu)
     return grub_error (GRUB_ERR_NET_PACKET_TOO_BIG, "packet too big");
 
-  grub_netbuff_push (nb, sizeof (*iph));
-  iph = (struct ip6hdr *) nb->data;
+  err = grub_netbuff_push (nb, sizeof (*iph));
+  if (err)
+    return err;
 
+  iph = (struct ip6hdr *) nb->data;
   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;
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
index 82af3a0ba..21a4e94d1 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/grub-core/net/netbuff.c b/grub-core/net/netbuff.c
index e97ecd23e..dbeeefe47 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/grub-core/net/tcp.c b/grub-core/net/tcp.c
index 2077f5519..1d90f1ec5 100644
--- a/grub-core/net/tcp.c
+++ b/grub-core/net/tcp.c
@@ -918,7 +918,7 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb,
 	      do_ack = 1;
 	    }
 	  else
-	    grub_netbuff_free (nb);
+	    grub_netbuff_free (nb_top);
 	}
       if (do_ack)
 	ack (sock);
diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c
index 3e4c337da..eeb7ec18c 100644
--- a/grub-core/normal/charset.c
+++ b/grub-core/normal/charset.c
@@ -929,6 +929,7 @@ grub_bidi_line_logical_to_visual (const grub_uint32_t *logical,
 	  case GRUB_BIDI_TYPE_R:
 	  case GRUB_BIDI_TYPE_AL:
 	    bidi_needed = 1;
+	    /* Fallthrough.  */
 	  default:
 	    {
 	      if (join_state == JOIN_FORCE)
diff --git a/grub-core/normal/color.c b/grub-core/normal/color.c
index c2654239f..d22cf903d 100644
--- a/grub-core/normal/color.c
+++ b/grub-core/normal/color.c
@@ -47,7 +47,7 @@ static int
 parse_color_name (grub_uint8_t *ret, char *name)
 {
   grub_uint8_t i;
-  for (i = 0; i < sizeof (color_list) / sizeof (*color_list); i++)
+  for (i = 0; i < ARRAY_SIZE(color_list); i++)
     if (! grub_strcmp (name, color_list[i]))
       {
         *ret = i;
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index c41f175bd..78a70a8bf 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -130,7 +130,7 @@ read_config_file (const char *config)
   file = grub_bufio_open (rawfile, 0);
   if (! file)
     {
-      grub_file_close (file);
+      grub_file_close (rawfile);
       return 0;
     }
 
@@ -445,7 +445,7 @@ grub_cmdline_run (int nested, int force_auth)
 
   while (1)
     {
-      char *line;
+      char *line = NULL;
 
       if (grub_normal_exit_level)
 	break;
diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c
index 2ff294101..e22bb91f6 100644
--- a/grub-core/normal/menu_text.c
+++ b/grub-core/normal/menu_text.c
@@ -369,6 +369,9 @@ grub_menu_init_page (int nested, int edit,
       geo->border = 0;
     }
 
+  if (geo->entry_width <= 0)
+    geo->entry_width = 1;
+
   if (geo->num_entries - msg_num_lines < 3
       && geo->timeout_lines == 2)
     {
diff --git a/grub-core/normal/misc.c b/grub-core/normal/misc.c
index 34d505eda..38f91b9b9 100644
--- a/grub-core/normal/misc.c
+++ b/grub-core/normal/misc.c
@@ -184,10 +184,11 @@ grub_normal_print_device_info (const char *name)
 		     /* TRANSLATORS: Replace dot with appropriate decimal separator for
 			your language.  */
 		     (grub_disk_get_size (dev->disk) & 1) ? _(".5") : "");
-
-      grub_device_close (dev);
     }
 
+  if (dev)
+    grub_device_close (dev);
+
   grub_xputs ("\n");
   return grub_errno;
 }
diff --git a/grub-core/osdep/aros/hostdisk.c b/grub-core/osdep/aros/hostdisk.c
index e1eeea7d0..7d99b54b8 100644
--- a/grub-core/osdep/aros/hostdisk.c
+++ b/grub-core/osdep/aros/hostdisk.c
@@ -61,7 +61,7 @@
 static ULONG *bounce;
 
 char *
-canonicalize_file_name (const char *path)
+grub_canonicalize_file_name (const char *path)
 {
   char *ret;
   BPTR lck;
diff --git a/grub-core/osdep/devmapper/getroot.c b/grub-core/osdep/devmapper/getroot.c
index d02386b34..0a77a04b9 100644
--- a/grub-core/osdep/devmapper/getroot.c
+++ b/grub-core/osdep/devmapper/getroot.c
@@ -160,7 +160,10 @@ grub_util_pull_devmapper (const char *os_dev)
   uuid = get_dm_uuid (os_dev);
 
   if (!grub_util_open_dm (os_dev, &tree, &node))
-    return;
+    {
+      grub_free (uuid);
+      return;
+    }
 
   while ((child = dm_tree_next_child (&handle, node, 0)))
     {
@@ -192,6 +195,7 @@ grub_util_pull_devmapper (const char *os_dev)
     }
   else
     dm_tree_free (tree);
+  grub_free (uuid);
 }
 
 char *
@@ -253,6 +257,7 @@ grub_util_get_devmapper_grub_dev (const char *os_dev)
       grub_free (uuid);
       return grub_dev;
     }
+  grub_free (uuid);
   return NULL;
 }
 
@@ -279,6 +284,7 @@ grub_util_get_vg_uuid (const char *os_dev)
     }
   optr--;
   *optr = '\0';
+  grub_free (uuid);
   return vgid;
 }
 
diff --git a/grub-core/osdep/haiku/getroot.c b/grub-core/osdep/haiku/getroot.c
index 0852c5e5e..4e123c090 100644
--- a/grub-core/osdep/haiku/getroot.c
+++ b/grub-core/osdep/haiku/getroot.c
@@ -65,7 +65,7 @@ grub_util_find_partition_start_os (const char *dev)
   device_geometry geo;
   if (ioctl (fd, B_GET_GEOMETRY, &geo, sizeof (geo)) < 0)
     return 0;
-  ret /= geo.bytes_per_sector;
+  ret /= geo.bytes_per_sector ? : 512;
   close (fd);  
   return ret;
 }
diff --git a/grub-core/osdep/linux/blocklist.c b/grub-core/osdep/linux/blocklist.c
index f33a7d507..c77d6085c 100644
--- a/grub-core/osdep/linux/blocklist.c
+++ b/grub-core/osdep/linux/blocklist.c
@@ -82,6 +82,8 @@ grub_install_get_blocklist (grub_device_t root_dev,
 			 strerror (errno));
       if (bsize & (GRUB_DISK_SECTOR_SIZE - 1))
 	grub_util_error ("%s", _("blocksize is not divisible by 512"));
+      if (!bsize)
+	grub_util_error ("%s", _("invalid zero blocksize"));
       mul = bsize >> GRUB_DISK_SECTOR_BITS;
       nblocks = (core_size + bsize - 1) / bsize;
       if (mul == 0 || nblocks == 0)
@@ -128,6 +130,7 @@ grub_install_get_blocklist (grub_device_t root_dev,
 		    & (GRUB_DISK_SECTOR_SIZE - 1),
 		    fie2->fm_extents[i].fe_length, hook_data);
 	}
+      free (fie2);
     }
   close (fd);
 }
diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c
index 7007193d9..a2e360f52 100644
--- a/grub-core/osdep/linux/getroot.c
+++ b/grub-core/osdep/linux/getroot.c
@@ -226,7 +226,7 @@ grub_find_root_devices_from_btrfs (const char *dir)
   char **ret;
 
   fd = open (dir, 0);
-  if (!fd)
+  if (fd < 0)
     return NULL;
 
   if (ioctl (fd, BTRFS_IOC_FS_INFO, &fsi) < 0)
@@ -274,11 +274,11 @@ get_btrfs_fs_prefix (const char *mount_path)
   args.objectid = GRUB_BTRFS_TREE_ROOT_OBJECTID;
   
   if (ioctl (fd, BTRFS_IOC_INO_LOOKUP, &args) < 0)
-    return NULL;
+    goto fail;
   tree_id = args.treeid;
 
   if (fstat (fd, &st) < 0)
-    return NULL;
+    goto fail;
   inode_id = st.st_ino;
 
   while (tree_id != GRUB_BTRFS_ROOT_VOL_OBJECTID
@@ -309,11 +309,11 @@ get_btrfs_fs_prefix (const char *mount_path)
 	  sargs.key.nr_items = 1;
 
 	  if (ioctl (fd, BTRFS_IOC_TREE_SEARCH, &sargs) < 0)
-	    return NULL;
+	    goto fail;
 
 	  if (sargs.key.nr_items == 0)
-	    return NULL;
-      
+	    goto fail;
+
 	  tree_id = sargs.buf[2];
 	  br = (struct grub_btrfs_root_backref *) (sargs.buf + 4);
 	  inode_id = br->inode_id;
@@ -336,10 +336,10 @@ get_btrfs_fs_prefix (const char *mount_path)
 	  sargs.key.max_type = GRUB_BTRFS_ITEM_TYPE_INODE_REF;
 
 	  if (ioctl (fd, BTRFS_IOC_TREE_SEARCH, &sargs) < 0)
-	    return NULL;
+	    goto fail;
 
 	  if (sargs.key.nr_items == 0)
-	    return NULL;
+	    goto fail;
 
 	  inode_id = sargs.buf[2];
 
@@ -360,8 +360,14 @@ get_btrfs_fs_prefix (const char *mount_path)
 	ret[1+namelen] = '\0';
     }
   if (!ret)
-    return xstrdup ("/");
+    ret = xstrdup ("/");
+  close (fd);
   return ret;
+
+ fail:
+  free (ret);
+  close (fd);
+  return NULL;
 }
 
 
@@ -688,7 +694,7 @@ char *
 grub_util_part_to_disk (const char *os_dev, struct stat *st,
 			int *is_part)
 {
-  char *path = xmalloc (PATH_MAX);
+  char *path;
 
   if (! S_ISBLK (st->st_mode))
     {
@@ -696,6 +702,8 @@ grub_util_part_to_disk (const char *os_dev, struct stat *st,
       return xstrdup (os_dev);
     }
 
+  path = xmalloc (PATH_MAX);
+
   if (! realpath (os_dev, path))
     return NULL;
 
diff --git a/grub-core/osdep/linux/hostdisk.c b/grub-core/osdep/linux/hostdisk.c
index c96427a56..06179fca7 100644
--- a/grub-core/osdep/linux/hostdisk.c
+++ b/grub-core/osdep/linux/hostdisk.c
@@ -376,7 +376,8 @@ grub_util_fd_open_device (const grub_disk_t disk, grub_disk_addr_t sector, int f
 
     part_start = grub_partition_get_start (disk->partition);
 
-    strcpy (dev, grub_util_biosdisk_get_osdev (disk));
+    strncpy (dev, grub_util_biosdisk_get_osdev (disk), sizeof (dev) - 1);
+    dev[sizeof(dev) - 1] = '\0';
     if (disk->partition
 	&& strncmp (dev, "/dev/", 5) == 0)
       {
@@ -439,7 +440,8 @@ grub_util_fd_open_device (const grub_disk_t disk, grub_disk_addr_t sector, int f
 	    if (*max == 0)
 	      *max = ~0ULL;
 	    is_partition = 0;
-	    strcpy (dev, grub_util_biosdisk_get_osdev (disk));
+	    strncpy (dev, grub_util_biosdisk_get_osdev (disk), sizeof (dev) - 1);
+	    dev[sizeof(dev) - 1] = '\0';
 	    goto reopen;
 	  }
 	sector -= part_start;
diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
index 8f24bc9e8..05b1ecdf8 100644
--- a/grub-core/osdep/linux/ofpath.c
+++ b/grub-core/osdep/linux/ofpath.c
@@ -122,12 +122,16 @@ find_obppath (const char *sysfs_path_orig)
       fd = open(path, O_RDONLY);
       if (fd < 0 || fstat (fd, &st) < 0)
 	{
+	  if (fd >= 0)
+	    close (fd);
 	  snprintf(path, path_size, "%s/devspec", sysfs_path);
 	  fd = open(path, O_RDONLY);
 	}
 
       if (fd < 0 || fstat (fd, &st) < 0)
 	{
+	  if (fd >= 0)
+	    close (fd);
 	  kill_trailing_dir(sysfs_path);
 	  if (!strcmp(sysfs_path, "/sys"))
 	    {
@@ -147,6 +151,9 @@ find_obppath (const char *sysfs_path_orig)
 	{
 	  grub_util_info (_("cannot read `%s': %s"), path, strerror (errno));
 	  close(fd);
+	  free (path);
+	  free (of_path);
+	  free (sysfs_path);
 	  return NULL;
 	}
       close(fd);
@@ -329,7 +336,7 @@ vendor_is_ATA(const char *path)
 }
 
 static void
-check_sas (char *sysfs_path, int *tgt, unsigned long int *sas_address)
+check_sas (const char *sysfs_path, int *tgt, unsigned long int *sas_address)
 {
   char *ed = strstr (sysfs_path, "end_device");
   char *p, *q, *path;
@@ -341,8 +348,10 @@ check_sas (char *sysfs_path, int *tgt, unsigned long int *sas_address)
     return;
 
   /* SAS devices are identified using disk@$PHY_ID */
-  p = strdup (sysfs_path);
+  p = xstrdup (sysfs_path);
   ed = strstr(p, "end_device");
+  if (!ed)
+    return;
 
   q = ed;
   while (*q && *q != '/')
@@ -480,6 +489,7 @@ of_path_of_scsi(const char *sys_devname __attribute__((unused)), const char *dev
               snprintf(disk, sizeof (disk),
                        "/sas/%s@%lx,%lu:%c", disk_name, sas_address, longlun, 'a' + (part - 1));
             }
+	  free (lunstr);
         }
     }
   strcat(of_path, disk);
@@ -530,7 +540,7 @@ grub_util_devname_to_ofpath (const char *sys_devname)
   else
     {
       grub_util_warn (_("unknown device type %s\n"), device);
-      return NULL;
+      ofpath = NULL;
     }
 
   free (devnode);
diff --git a/grub-core/osdep/linux/platform.c b/grub-core/osdep/linux/platform.c
index 4b9f6ef9d..775b6c031 100644
--- a/grub-core/osdep/linux/platform.c
+++ b/grub-core/osdep/linux/platform.c
@@ -60,6 +60,43 @@ is_64_kernel (void)
   return strcmp (un.machine, "x86_64") == 0;
 }
 
+static int
+read_platform_size (void)
+{
+  FILE *fp;
+  char *buf = NULL;
+  size_t len = 0;
+  int ret = 0;
+
+  /* Newer kernels can tell us directly about the size of the
+   * underlying firmware - let's see if that interface is there. */
+  fp = grub_util_fopen ("/sys/firmware/efi/fw_platform_size", "r");
+  if (fp != NULL)
+  {
+    if (getline (&buf, &len, fp) >= 3) /* 2 digits plus newline */
+      {
+	if (strncmp (buf, "32", 2) == 0)
+	  ret = 32;
+	else if (strncmp (buf, "64", 2) == 0)
+	  ret = 64;
+      }
+    free (buf);
+    fclose (fp);
+  }
+
+  if (ret == 0)
+    {
+      /* Unrecognised - fall back to matching the kernel size
+       * instead */
+      if (is_64_kernel ())
+	ret = 64;
+      else
+	ret = 32;
+    }
+
+  return ret;
+}
+
 const char *
 grub_install_get_default_x86_platform (void)
 { 
@@ -77,7 +114,7 @@ grub_install_get_default_x86_platform (void)
   if (is_not_empty_directory ("/sys/firmware/efi"))
     {
       grub_util_info ("...found");
-      if (is_64_kernel ())
+      if (read_platform_size() == 64)
 	return "x86_64-efi";
       else
 	return "i386-efi";
diff --git a/grub-core/osdep/unix/cputime.c b/grub-core/osdep/unix/cputime.c
index 47e3abc77..cff359a3b 100644
--- a/grub-core/osdep/unix/cputime.c
+++ b/grub-core/osdep/unix/cputime.c
@@ -9,7 +9,14 @@ grub_uint64_t
 grub_util_get_cpu_time_ms (void)
 {
   struct tms tm;
+  static long sc_clk_tck;
+  if (!sc_clk_tck)
+    {
+      sc_clk_tck = sysconf(_SC_CLK_TCK);
+      if (sc_clk_tck <= 0)
+	sc_clk_tck = 1000;
+    }
 
   times (&tm); 
-  return (tm.tms_utime * 1000ULL) / sysconf(_SC_CLK_TCK);
+  return (tm.tms_utime * 1000ULL) / sc_clk_tck;
 }
diff --git a/grub-core/osdep/unix/getroot.c b/grub-core/osdep/unix/getroot.c
index e3887cbea..b98b2dfb0 100644
--- a/grub-core/osdep/unix/getroot.c
+++ b/grub-core/osdep/unix/getroot.c
@@ -57,6 +57,9 @@
 #endif
 
 #include <sys/types.h>
+#if defined(HAVE_SYS_MKDEV_H)
+#include <sys/mkdev.h>
+#endif
 
 #if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
 # include <grub/util/libzfs.h>
@@ -491,7 +494,7 @@ grub_guess_root_devices (const char *dir_in)
   char **os_dev = NULL;
   struct stat st;
   dev_t dev;
-  char *dir = canonicalize_file_name (dir_in);
+  char *dir = grub_canonicalize_file_name (dir_in);
 
   if (!dir)
     grub_util_error (_("failed to get canonical path of `%s'"), dir_in);
@@ -516,7 +519,7 @@ grub_guess_root_devices (const char *dir_in)
 	    *cur = tmp;
 	  else
 	    {
-	      *cur = canonicalize_file_name (tmp);
+	      *cur = grub_canonicalize_file_name (tmp);
 	      if (*cur == NULL)
 		grub_util_error (_("failed to get canonical path of `%s'"), tmp);
 	      free (tmp);
@@ -621,7 +624,10 @@ grub_util_pull_lvm_by_command (const char *os_dev)
   free (vgname);
 
   if (!pid)
-    return;
+    {
+      free (vgid);
+      return;
+    }
 
   /* Parent.  Read vgs' output.  */
   vgs = fdopen (fd, "r");
@@ -653,6 +659,7 @@ out:
   close (fd);
   waitpid (pid, NULL, 0);
   free (buf);
+  free (vgid);
 }
 
 /* ZFS has similar problems to those of btrfs (see above).  */
diff --git a/grub-core/osdep/unix/hostdisk.c b/grub-core/osdep/unix/hostdisk.c
index 43b56ff31..2a8c5882e 100644
--- a/grub-core/osdep/unix/hostdisk.c
+++ b/grub-core/osdep/unix/hostdisk.c
@@ -48,11 +48,6 @@
 #ifdef __linux__
 # include <sys/ioctl.h>         /* ioctl */
 # include <sys/mount.h>
-# if !defined(__GLIBC__) || \
-        ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
-/* Maybe libc doesn't have large file support.  */
-#  include <linux/unistd.h>     /* _llseek */
-# endif /* (GLIBC < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR < 1)) */
 #endif /* __linux__ */
 
 grub_uint64_t
@@ -79,24 +74,6 @@ grub_util_get_fd_size (grub_util_fd_t fd, const char *name, unsigned *log_secsiz
   return st.st_size;
 }
 
-#if defined(__linux__) && (!defined(__GLIBC__) || \
-        ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))))
-  /* Maybe libc doesn't have large file support.  */
-int
-grub_util_fd_seek (grub_util_fd_t fd, grub_uint64_t off)
-{
-  loff_t offset, result;
-  static int _llseek (uint filedes, ulong hi, ulong lo,
-		      loff_t *res, uint wh);
-  _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
-	     loff_t *, res, uint, wh);
-
-  offset = (loff_t) off;
-  if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
-    return -1;
-  return GRUB_ERR_NONE;
-}
-#else
 int
 grub_util_fd_seek (grub_util_fd_t fd, grub_uint64_t off)
 {
@@ -107,7 +84,6 @@ grub_util_fd_seek (grub_util_fd_t fd, grub_uint64_t off)
 
   return 0;
 }
-#endif
 
 
 /* Read LEN bytes from FD in BUF. Return less than or equal to zero if an
@@ -222,7 +198,7 @@ grub_util_fd_close (grub_util_fd_t fd)
 }
 
 char *
-canonicalize_file_name (const char *path)
+grub_canonicalize_file_name (const char *path)
 {
 #if defined (PATH_MAX)
   char *ret;
diff --git a/grub-core/osdep/unix/password.c b/grub-core/osdep/unix/password.c
index 470a6ea62..4b9507bce 100644
--- a/grub-core/osdep/unix/password.c
+++ b/grub-core/osdep/unix/password.c
@@ -53,7 +53,10 @@ grub_password_get (char buf[], unsigned buf_size)
     tty_changed = 0;
   grub_memset (buf, 0, buf_size);
   if (!fgets (buf, buf_size, stdin))
-    return 0;
+    {
+      fclose (in);
+      return 0;
+    }
   ptr = buf + strlen (buf) - 1;
   while (buf <= ptr && (*ptr == '\n' || *ptr == '\r'))
     *ptr-- = 0;
@@ -64,5 +67,7 @@ grub_password_get (char buf[], unsigned buf_size)
   grub_xputs ("\n");
   grub_refresh ();
 
+  fclose (in);
+
   return 1;
 }
diff --git a/grub-core/osdep/unix/relpath.c b/grub-core/osdep/unix/relpath.c
index 71c19d867..8fdc3a73a 100644
--- a/grub-core/osdep/unix/relpath.c
+++ b/grub-core/osdep/unix/relpath.c
@@ -44,7 +44,7 @@ grub_make_system_path_relative_to_its_root (const char *path)
   char *poolfs = NULL;
 
   /* canonicalize.  */
-  p = canonicalize_file_name (path);
+  p = grub_canonicalize_file_name (path);
   if (p == NULL)
     grub_util_error (_("failed to get canonical path of `%s'"), path);
 
diff --git a/grub-core/osdep/windows/hostdisk.c b/grub-core/osdep/windows/hostdisk.c
index d390b25fc..85507af88 100644
--- a/grub-core/osdep/windows/hostdisk.c
+++ b/grub-core/osdep/windows/hostdisk.c
@@ -328,7 +328,7 @@ grub_util_fd_strerror (void)
 }
 
 char *
-canonicalize_file_name (const char *path)
+grub_canonicalize_file_name (const char *path)
 {
   char *ret;
   LPTSTR windows_path;
diff --git a/grub-core/osdep/windows/init.c b/grub-core/osdep/windows/init.c
index 98c325c20..e8ffd62c6 100644
--- a/grub-core/osdep/windows/init.c
+++ b/grub-core/osdep/windows/init.c
@@ -170,7 +170,7 @@ grub_util_host_init (int *argc __attribute__ ((unused)),
 #error "Unsupported TCHAR size"
 #endif
 
-  grub_util_base_directory = canonicalize_file_name ((*argv)[0]);
+  grub_util_base_directory = grub_canonicalize_file_name ((*argv)[0]);
   if (!grub_util_base_directory)
     grub_util_base_directory = xstrdup ((*argv)[0]);
   for (ptr = grub_util_base_directory + strlen (grub_util_base_directory) - 1;
diff --git a/grub-core/partmap/sun.c b/grub-core/partmap/sun.c
index dae360269..aac30a320 100644
--- a/grub-core/partmap/sun.c
+++ b/grub-core/partmap/sun.c
@@ -91,7 +91,7 @@ sun_partition_map_iterate (grub_disk_t disk,
   struct grub_partition p;
   union
   {
-    struct grub_sun_block sun;
+    struct grub_sun_block sun_block;
     grub_uint16_t raw[0];
   } block;
   int partnum;
@@ -103,7 +103,7 @@ sun_partition_map_iterate (grub_disk_t disk,
   if (err)
     return err;
 
-  if (GRUB_PARTMAP_SUN_MAGIC != grub_be_to_cpu16 (block.sun.magic))
+  if (GRUB_PARTMAP_SUN_MAGIC != grub_be_to_cpu16 (block.sun_block.magic))
     return grub_error (GRUB_ERR_BAD_PART_TABLE, "not a sun partition table");
 
   if (! grub_sun_is_valid (block.raw))
@@ -115,14 +115,14 @@ sun_partition_map_iterate (grub_disk_t disk,
     {
       struct grub_sun_partition_descriptor *desc;
 
-      if (block.sun.infos[partnum].id == 0
-	  || block.sun.infos[partnum].id == GRUB_PARTMAP_SUN_WHOLE_DISK_ID)
+      if (block.sun_block.infos[partnum].id == 0
+	  || block.sun_block.infos[partnum].id == GRUB_PARTMAP_SUN_WHOLE_DISK_ID)
 	continue;
 
-      desc = &block.sun.partitions[partnum];
+      desc = &block.sun_block.partitions[partnum];
       p.start = ((grub_uint64_t) grub_be_to_cpu32 (desc->start_cylinder)
-		  * grub_be_to_cpu16 (block.sun.ntrks)
-		  * grub_be_to_cpu16 (block.sun.nsect));
+		  * grub_be_to_cpu16 (block.sun_block.ntrks)
+		  * grub_be_to_cpu16 (block.sun_block.nsect));
       p.len = grub_be_to_cpu32 (desc->num_sectors);
       p.number = p.index = partnum;
       if (p.len)
diff --git a/grub-core/partmap/sunpc.c b/grub-core/partmap/sunpc.c
index 442763ee5..73a430c14 100644
--- a/grub-core/partmap/sunpc.c
+++ b/grub-core/partmap/sunpc.c
@@ -74,7 +74,7 @@ sun_pc_partition_map_iterate (grub_disk_t disk,
   grub_partition_t p;
   union
   {
-    struct grub_sun_pc_block sun;
+    struct grub_sun_pc_block sun_block;
     grub_uint16_t raw[0];
   } block;
   int partnum;
@@ -92,7 +92,7 @@ sun_pc_partition_map_iterate (grub_disk_t disk,
       return err;
     }
   
-  if (GRUB_PARTMAP_SUN_PC_MAGIC != grub_le_to_cpu16 (block.sun.magic))
+  if (GRUB_PARTMAP_SUN_PC_MAGIC != grub_le_to_cpu16 (block.sun_block.magic))
     {
       grub_free (p);
       return grub_error (GRUB_ERR_BAD_PART_TABLE, 
@@ -111,12 +111,12 @@ sun_pc_partition_map_iterate (grub_disk_t disk,
     {
       struct grub_sun_pc_partition_descriptor *desc;
 
-      if (block.sun.partitions[partnum].id == 0
-	  || block.sun.partitions[partnum].id
+      if (block.sun_block.partitions[partnum].id == 0
+	  || block.sun_block.partitions[partnum].id
 	  == GRUB_PARTMAP_SUN_PC_WHOLE_DISK_ID)
 	continue;
 
-      desc = &block.sun.partitions[partnum];
+      desc = &block.sun_block.partitions[partnum];
       p->start = grub_le_to_cpu32 (desc->start_sector);
       p->len = grub_le_to_cpu32 (desc->num_sectors);
       p->number = partnum;
diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c
index afd551320..bb70ebf17 100644
--- a/grub-core/script/execute.c
+++ b/grub-core/script/execute.c
@@ -635,57 +635,77 @@ grub_script_arglist_to_argv (struct grub_script_arglist *arglist,
 	    {
 	    case GRUB_SCRIPT_ARG_TYPE_VAR:
 	    case GRUB_SCRIPT_ARG_TYPE_DQVAR:
-	      values = grub_script_env_get (arg->str, arg->type);
-	      for (i = 0; values && values[i]; i++)
-		{
-		  if (i != 0 && grub_script_argv_next (&result))
-		    goto fail;
+	      {
+		int need_cleanup = 0;
 
-		  if (arg->type == GRUB_SCRIPT_ARG_TYPE_VAR)
-		    {
-		      int len;
-		      char ch;
-		      char *p;
-		      char *op;
-		      const char *s = values[i];
+		values = grub_script_env_get (arg->str, arg->type);
+		for (i = 0; values && values[i]; i++)
+		  {
+		    if (!need_cleanup)
+		      {
+			if (i != 0 && grub_script_argv_next (&result))
+			  {
+			    need_cleanup = 1;
+			    goto cleanup;
+			  }
 
-		      len = grub_strlen (values[i]);
-		      /* \? -> \\\? */
-		      /* \* -> \\\* */
-		      /* \ -> \\ */
-		      p = grub_malloc (len * 2 + 1);
-		      if (! p)
-			goto fail;
+			if (arg->type == GRUB_SCRIPT_ARG_TYPE_VAR)
+			  {
+			    int len;
+			    char ch;
+			    char *p;
+			    char *op;
+			    const char *s = values[i];
 
-		      op = p;
-		      while ((ch = *s++))
-			{
-			  if (ch == '\\')
-			    {
-			      *op++ = '\\';
-			      if (*s == '?' || *s == '*')
-				*op++ = '\\';
-			    }
-			  *op++ = ch;
-			}
-		      *op = '\0';
+			    len = grub_strlen (values[i]);
+			    /* \? -> \\\? */
+			    /* \* -> \\\* */
+			    /* \ -> \\ */
+			    p = grub_malloc (len * 2 + 1);
+			    if (! p)
+			      {
+				need_cleanup = 1;
+				goto cleanup;
+			      }
 
-		      if (grub_script_argv_append (&result, p, op - p))
-			{
-			  grub_free (p);
-			  goto fail;
-			}
-		    }
-		  else
-		    {
-		      if (append (&result, values[i], 1))
-			goto fail;
-		    }
+			    op = p;
+			    while ((ch = *s++))
+			      {
+				if (ch == '\\')
+				  {
+				    *op++ = '\\';
+				    if (*s == '?' || *s == '*')
+				      *op++ = '\\';
+				  }
+				*op++ = ch;
+			      }
+			    *op = '\0';
 
-		  grub_free (values[i]);
-		}
-	      grub_free (values);
-	      break;
+			    if (grub_script_argv_append (&result, p, op - p))
+			      {
+				grub_free (p);
+				need_cleanup = 1;
+				/* Fall through to cleanup */
+			      }
+			  }
+			else
+			  {
+			    if (append (&result, values[i], 1))
+			      need_cleanup = 1;
+			      /* Fall through to cleanup */
+			  }
+		      }
+
+cleanup:
+		    grub_free (values[i]);
+		  }
+		grub_free (values);
+
+		if (need_cleanup)
+		  goto fail;
+
+		break;
+	      }
 
 	    case GRUB_SCRIPT_ARG_TYPE_BLOCK:
 	      {
diff --git a/grub-core/script/lexer.c b/grub-core/script/lexer.c
index 128d23822..89cf67706 100644
--- a/grub-core/script/lexer.c
+++ b/grub-core/script/lexer.c
@@ -164,6 +164,7 @@ grub_script_lexer_yywrap (struct grub_parser_param *parserstate,
     {
       grub_free (line);
       line = grub_strdup ("\n");
+      len = 1;
     }
   else if (len && line[len - 1] != '\n')
     {
diff --git a/grub-core/term/gfxterm.c b/grub-core/term/gfxterm.c
index dc0669b35..70f10f19c 100644
--- a/grub-core/term/gfxterm.c
+++ b/grub-core/term/gfxterm.c
@@ -221,6 +221,8 @@ grub_virtual_screen_setup (unsigned int x, unsigned int y,
     calculate_normal_character_width (virtual_screen.font);
   virtual_screen.normal_char_height =
     grub_font_get_max_char_height (virtual_screen.font);
+  if (virtual_screen.normal_char_height == 0)
+    virtual_screen.normal_char_height = 16;
   virtual_screen.cursor_x = 0;
   virtual_screen.cursor_y = 0;
   virtual_screen.cursor_state = 1;
diff --git a/grub-core/term/ns8250.c b/grub-core/term/ns8250.c
index 2959632a9..39809d042 100644
--- a/grub-core/term/ns8250.c
+++ b/grub-core/term/ns8250.c
@@ -57,6 +57,8 @@ serial_get_divisor (const struct grub_serial_port *port __attribute__ ((unused))
   base_clock = config->base_clock ? (config->base_clock >> 4) : DEFAULT_BASE_CLOCK;
 
   divisor = (base_clock + (config->speed / 2)) / config->speed;
+  if (config->speed == 0)
+    return 0;
   if (divisor > 0xffff || divisor == 0)
     return 0;
   actual_speed = base_clock / divisor;
diff --git a/grub-core/term/serial.c b/grub-core/term/serial.c
index c9b5574ae..db80b3ba0 100644
--- a/grub-core/term/serial.c
+++ b/grub-core/term/serial.c
@@ -220,8 +220,12 @@ grub_cmd_serial (grub_extcmd_context_t ctxt, int argc, char **args)
 
   config = port->config;
 
-  if (state[OPTION_SPEED].set)
+  if (state[OPTION_SPEED].set) {
     config.speed = grub_strtoul (state[OPTION_SPEED].arg, 0, 0);
+    if (config.speed == 0)
+      return grub_error (GRUB_ERR_BAD_ARGUMENT,
+			 N_("unsupported serial port parity"));
+  }
 
   if (state[OPTION_WORD].set)
     config.word_len = grub_strtoul (state[OPTION_WORD].arg, 0, 0);
@@ -241,9 +245,9 @@ grub_cmd_serial (grub_extcmd_context_t ctxt, int argc, char **args)
 
   if (state[OPTION_RTSCTS].set)
     {
-      if (grub_strcmp (state[OPTION_PARITY].arg, "on") == 0)
+      if (grub_strcmp (state[OPTION_RTSCTS].arg, "on") == 0)
 	config.rtscts = 1;
-      if (grub_strcmp (state[OPTION_PARITY].arg, "off") == 0)
+      else if (grub_strcmp (state[OPTION_RTSCTS].arg, "off") == 0)
 	config.rtscts = 0;
       else
 	return grub_error (GRUB_ERR_BAD_ARGUMENT,
@@ -275,6 +279,9 @@ grub_cmd_serial (grub_extcmd_context_t ctxt, int argc, char **args)
 	config.base_clock *= 1000;
     }
 
+  if (config.speed == 0)
+    config.speed = 9600;
+
   /* Initialize with new settings.  */
   err = port->driver->configure (port, &config);
   if (err)
diff --git a/grub-core/tests/boot/kernel-8086.S b/grub-core/tests/boot/kernel-8086.S
index 510897c88..5ec5368ff 100644
--- a/grub-core/tests/boot/kernel-8086.S
+++ b/grub-core/tests/boot/kernel-8086.S
@@ -46,5 +46,5 @@ message:
 	.ascii "Boot Test Passed Successfully\n" SUCCESSFUL_BOOT_STRING "\n"
 	.byte 0
 
-	. = base + 510
-	.short 0xaa55
\ No newline at end of file
+	.org 510
+	.short 0xaa55
diff --git a/grub-core/tests/bswap_test.c b/grub-core/tests/bswap_test.c
new file mode 100644
index 000000000..4eb3a9814
--- /dev/null
+++ b/grub-core/tests/bswap_test.c
@@ -0,0 +1,121 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2015 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/test.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static grub_uint64_t vectors[] = {
+  0xffffffffffffffffULL, 1, 2, 0, 0x0102030405060708ULL
+};
+
+static void
+test16 (grub_uint16_t a)
+{
+  grub_uint16_t b, c;
+  grub_uint8_t *ap, *bp;
+  int i;
+  b = grub_swap_bytes16 (a);
+  c = grub_swap_bytes16 (b);
+  grub_test_assert (a == c, "bswap not idempotent: 0x%llx, 0x%llx, 0x%llx",
+		    (long long) a, (long long) b, (long long) c);
+  ap = (grub_uint8_t *) &a;
+  bp = (grub_uint8_t *) &b;
+  for (i = 0; i < 2; i++)
+    {
+      grub_test_assert (ap[i] == bp[1 - i],
+			"bswap bytes wrong: 0x%llx, 0x%llx",
+			(long long) a, (long long) b);
+    }
+}
+
+static void
+test32 (grub_uint32_t a)
+{
+  grub_uint32_t b, c;
+  grub_uint8_t *ap, *bp;
+  int i;
+  b = grub_swap_bytes32 (a);
+  c = grub_swap_bytes32 (b);
+  grub_test_assert (a == c, "bswap not idempotent: 0x%llx, 0x%llx, 0x%llx",
+		    (long long) a, (long long) b, (long long) c);
+  ap = (grub_uint8_t *) &a;
+  bp = (grub_uint8_t *) &b;
+  for (i = 0; i < 4; i++)
+    {
+      grub_test_assert (ap[i] == bp[3 - i],
+			"bswap bytes wrong: 0x%llx, 0x%llx",
+			(long long) a, (long long) b);
+    }
+}
+
+static void
+test64 (grub_uint64_t a)
+{
+  grub_uint64_t b, c;
+  grub_uint8_t *ap, *bp;
+  int i;
+  b = grub_swap_bytes64 (a);
+  c = grub_swap_bytes64 (b);
+  grub_test_assert (a == c, "bswap not idempotent: 0x%llx, 0x%llx, 0x%llx",
+		    (long long) a, (long long) b, (long long) c);
+  ap = (grub_uint8_t *) &a;
+  bp = (grub_uint8_t *) &b;
+  for (i = 0; i < 4; i++)
+    {
+      grub_test_assert (ap[i] == bp[7 - i],
+			"bswap bytes wrong: 0x%llx, 0x%llx",
+			(long long) a, (long long) b);
+    }
+}
+
+static void
+test_all(grub_uint64_t a)
+{
+  test64 (a);
+  test32 (a);
+  test16 (a);
+}
+
+static void
+bswap_test (void)
+{
+  grub_uint64_t a = 404, b = 7;
+  grub_size_t i;
+
+  for (i = 0; i < ARRAY_SIZE (vectors); i++)
+    {
+      test_all (vectors[i]);
+    }
+  for (i = 0; i < 40000; i++)
+    {
+      a = 17 * a + 13 * b;
+      b = 23 * a + 29 * b;
+      if (b == 0)
+	b = 1;
+      if (a == 0)
+	a = 1;
+      test_all (a);
+      test_all (b);
+    }
+}
+
+/* Register example_test method as a functional test.  */
+GRUB_FUNCTIONAL_TEST (bswap_test, bswap_test);
diff --git a/grub-core/tests/cmp_test.c b/grub-core/tests/cmp_test.c
new file mode 100644
index 000000000..af5b39576
--- /dev/null
+++ b/grub-core/tests/cmp_test.c
@@ -0,0 +1,190 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2015 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/test.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static grub_uint64_t vectors[][2] = {
+  { 0xffffffffffffffffULL, 1},
+  { 1, 0xffffffffffffffffULL},
+  { 0xffffffffffffffffULL, 0xffffffffffffffffULL},
+  { 1, 1 },
+  { 2, 1 }
+};
+
+/* Don't change those to use shift as shift may call to compile rt
+   functions and we're not testing them now.
+ */
+static int
+leading_bit64 (grub_uint64_t a)
+{
+  return !!(a & 0x8000000000000000LL);
+}
+
+static int
+leading_bit32 (grub_uint32_t a)
+{
+  return !!(a & 0x80000000);
+}
+
+/* Computes (a < b) without involving comparison operator.  */
+static int
+is_less32 (grub_uint32_t a, grub_uint32_t b)
+{
+  if (leading_bit32(a) && !leading_bit32(b))
+    return 0;
+  if (!leading_bit32(a) && leading_bit32(b))
+    return 1;
+  return leading_bit32(a - b);
+}
+
+static void
+test32 (grub_uint32_t a, grub_uint32_t b)
+{
+  grub_test_assert ((a < b) == is_less32(a, b), "comparison result mismatch: %lld, %lld",
+		    (long long) a, (long long) b);
+  grub_test_assert ((a > b) == is_less32(b, a), "comparison result mismatch: %lld, %lld",
+		    (long long) a, (long long) b);
+  grub_test_assert ((b < a) == is_less32(b, a), "comparison result mismatch: %lld, %lld",
+		    (long long) a, (long long) b);
+  grub_test_assert ((b > a) == is_less32(a, b), "comparison result mismatch: %lld, %lld",
+		    (long long) a, (long long) b);
+  grub_test_assert (!(is_less32(a, b) && is_less32(b, a)), "comparison inconsistent: %lld, %lld",
+		    (long long) a, (long long) b);
+}
+
+/* Computes (a > b) without involving comparison operator.  */
+static int
+is_less32s (grub_int32_t a, grub_int32_t b)
+{
+  if (leading_bit32(a) && !leading_bit32(b))
+    return 1; /* a < 0 && b >= 0. */
+  if (!leading_bit32(a) && leading_bit32(b))
+    return 0; /* b < 0 && a >= 0. */
+  return leading_bit32(a - b);
+}
+
+static void
+test32s (grub_int32_t a, grub_int32_t b)
+{
+  grub_test_assert ((a < b) == is_less32s(a, b), "comparison result mismatch: %lld, %lld",
+		    (long long) a, (long long) b);
+  grub_test_assert ((a > b) == is_less32s(b, a), "comparison result mismatch: %lld, %lld",
+		    (long long) a, (long long) b);
+  grub_test_assert ((b < a) == is_less32s(b, a), "comparison result mismatch: %lld, %lld",
+		    (long long) a, (long long) b);
+  grub_test_assert ((b > a) == is_less32s(a, b), "comparison result mismatch: %lld, %lld",
+		    (long long) a, (long long) b);
+  grub_test_assert (!(is_less32s(a, b) && is_less32s(b, a)), "comparison inconsistent: %lld, %lld",
+		    (long long) a, (long long) b);
+}
+
+/* Computes (a > b) without involving comparison operator.  */
+static int
+is_less64 (grub_uint64_t a, grub_uint64_t b)
+{
+  if (leading_bit64(a) && !leading_bit64(b))
+    return 0;
+  if (!leading_bit64(a) && leading_bit64(b))
+    return 1;
+  return leading_bit64(a - b);
+}
+
+static void
+test64 (grub_uint64_t a, grub_uint64_t b)
+{
+  grub_test_assert ((a < b) == is_less64(a, b), "comparison result mismatch: %lld, %lld",
+		    (long long) a, (long long) b);
+  grub_test_assert ((a > b) == is_less64(b, a), "comparison result mismatch: %lld, %lld",
+		    (long long) a, (long long) b);
+  grub_test_assert ((b < a) == is_less64(b, a), "comparison result mismatch: %lld, %lld",
+		    (long long) a, (long long) b);
+  grub_test_assert ((b > a) == is_less64(a, b), "comparison result mismatch: %lld, %lld",
+		    (long long) a, (long long) b);
+  grub_test_assert (!(is_less64(a, b) && is_less64(b, a)), "comparison inconsistent: %lld, %lld",
+		    (long long) a, (long long) b);
+}
+
+/* Computes (a > b) without involving comparison operator.  */
+static int
+is_less64s (grub_int64_t a, grub_int64_t b)
+{
+  if (leading_bit64(a) && !leading_bit64(b))
+    return 1; /* a < 0 && b >= 0. */
+  if (!leading_bit64(a) && leading_bit64(b))
+    return 0; /* b < 0 && a >= 0. */
+  return leading_bit64(a - b);
+}
+
+static void
+test64s (grub_int64_t a, grub_int64_t b)
+{
+  grub_test_assert ((a < b) == is_less64s(a, b), "comparison result mismatch: %lld, %lld",
+		    (long long) a, (long long) b);
+  grub_test_assert ((a > b) == is_less64s(b, a), "comparison result mismatch: %lld, %lld",
+		    (long long) a, (long long) b);
+  grub_test_assert ((b < a) == is_less64s(b, a), "comparison result mismatch: %lld, %lld",
+		    (long long) a, (long long) b);
+  grub_test_assert ((b > a) == is_less64s(a, b), "comparison result mismatch: %lld, %lld",
+		    (long long) a, (long long) b);
+  grub_test_assert (!(is_less64s(a, b) && is_less64s(b, a)), "comparison inconsistent: %lld, %lld",
+		    (long long) a, (long long) b);
+}
+
+static void
+test_all(grub_uint64_t a, grub_uint64_t b)
+{
+  test64 (a, b);
+  test32 (a, b);
+  test64s (a, b);
+  test32s (a, b);
+  test64s (a, -b);
+  test32s (a, -b);
+  test64s (-a, b);
+  test32s (-a, b);
+  test64s (-a, -b);
+  test32s (-a, -b);
+}
+
+static void
+cmp_test (void)
+{
+  grub_uint64_t a = 404, b = 7;
+  grub_size_t i;
+
+  for (i = 0; i < ARRAY_SIZE (vectors); i++)
+    {
+      test_all (vectors[i][0], vectors[i][1]);
+    }
+  for (i = 0; i < 40000; i++)
+    {
+      a = 17 * a + 13 * b;
+      b = 23 * a + 29 * b;
+      if (b == 0)
+	b = 1;
+      if (a == 0)
+	a = 1;
+      test_all (a, b);
+    }
+}
+
+/* Register example_test method as a functional test.  */
+GRUB_FUNCTIONAL_TEST (cmp_test, cmp_test);
diff --git a/grub-core/tests/ctz_test.c b/grub-core/tests/ctz_test.c
new file mode 100644
index 000000000..eb7a1df38
--- /dev/null
+++ b/grub-core/tests/ctz_test.c
@@ -0,0 +1,111 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/test.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+/* ull version is not used on i386 other than in this test.
+   Avoid requiring extra function.
+  */
+#if defined (__i386__)
+#define SKIP_ULL 1
+#endif
+
+static grub_uint64_t vectors[] = {
+  0xffffffffffffffffULL, 1, 2, 0, 0x0102030405060708ULL
+};
+
+static void
+test_ui (unsigned int a)
+{
+  int i;
+  a |= 1;
+  for (i = 0; i < (int) (8 * sizeof (a)); i++)
+    {
+      grub_test_assert (__builtin_ctz(a << i) == i,
+			"ctz mismatch: ctz(0x%llx) != 0x%x",
+			(long long) (a << i), __builtin_ctz(a << i));
+    }
+}
+
+static void
+test_ul (unsigned long a)
+{
+  int i;
+  a |= 1;
+  for (i = 0; i < (int) (8 * sizeof (a)); i++)
+    {
+      grub_test_assert (__builtin_ctzl(a << i) == i,
+			"ctzl mismatch: ctzl(0x%llx) != 0x%x",
+			(long long) (a << i), __builtin_ctz(a << i));
+    }
+}
+
+#ifndef SKIP_ULL
+static void
+test_ull (unsigned long long a)
+{
+  int i;
+  a |= 1;
+  for (i = 0; i < (int) (8 * sizeof (a)); i++)
+    {
+      grub_test_assert (__builtin_ctzll(a << i) == i,
+			"ctzll mismatch: ctzll(0x%llx) != 0x%x",
+			(long long) (a << i), __builtin_ctz(a << i));
+    }
+}
+#endif
+
+static void
+test_all(grub_uint64_t a)
+{
+  test_ui (a);
+  test_ul (a);
+#ifndef SKIP_ULL
+  test_ull (a);
+#endif
+}
+
+static void
+ctz_test (void)
+{
+  grub_uint64_t a = 404, b = 7;
+  grub_size_t i;
+
+  for (i = 0; i < ARRAY_SIZE (vectors); i++)
+    {
+      test_all (vectors[i]);
+    }
+  for (i = 0; i < 40000; i++)
+    {
+      a = 17 * a + 13 * b;
+      b = 23 * a + 29 * b;
+      if (b == 0)
+	b = 1;
+      if (a == 0)
+	a = 1;
+      test_all (a);
+      test_all (b);
+    }
+}
+
+/* Register example_test method as a functional test.  */
+GRUB_FUNCTIONAL_TEST (ctz_test, ctz_test);
diff --git a/grub-core/tests/div_test.c b/grub-core/tests/div_test.c
index 1928f8507..9abc6d5c4 100644
--- a/grub-core/tests/div_test.c
+++ b/grub-core/tests/div_test.c
@@ -34,6 +34,8 @@ static void
 test32 (grub_uint32_t a, grub_uint32_t b)
 {
   grub_uint64_t q, r;
+  if (b == 0)
+    return;
   q = grub_divmod64 (a, b, &r);
   grub_test_assert (r < b, "remainder is larger than dividend: 0x%llx %% 0x%llx = 0x%llx",
 		    (long long) a, (long long) b, (long long) r);
@@ -95,6 +97,72 @@ test64 (grub_uint64_t a, grub_uint64_t b)
 #endif
 }
 
+static grub_int64_t
+abs64(grub_int64_t a)
+{
+  return a > 0 ? a : -a;
+}
+
+static void
+test32s (grub_int32_t a, grub_int32_t b)
+{
+  grub_int64_t q, r;
+  if (b == 0)
+    return;
+
+  q = grub_divmod64s (a, b, &r);
+  grub_test_assert (a > 0 ? r >= 0 : r <= 0, "remainder sign mismatch: %lld %% %lld = %lld",
+		    (long long) a, (long long) b, (long long) r);
+  grub_test_assert (((a > 0) == (b > 0)) ? q >= 0 : q <= 0, "quotient sign mismatch: %lld / %lld = %lld",
+		    (long long) a, (long long) b, (long long) q);
+  grub_test_assert (abs64(r) < abs64(b), "remainder is larger than dividend: %lld %% %lld = %lld",
+		    (long long) a, (long long) b, (long long) r);
+  grub_test_assert (q * b + r == a, "division doesn't satisfy base property: %lld * %lld + %lld != %lld", (long long) q, (long long) b, (long long) r,
+		    (long long) a);
+  if (0) {  grub_test_assert (q == (a / b),
+		    "C compiler division failure in 0x%llx, 0x%llx", (long long) a, (long long) b);
+  grub_test_assert (r == (a % b),
+		    "C compiler modulo failure in 0x%llx, 0x%llx", (long long) a, (long long) b);
+  }
+}
+
+static void
+test64s (grub_int64_t a, grub_int64_t b)
+{
+  grub_int64_t q, r;
+  q = grub_divmod64s (a, b, &r);
+
+  grub_test_assert (a > 0 ? r >= 0 : r <= 0, "remainder sign mismatch: %lld %% %lld = %lld",
+		    (long long) a, (long long) b, (long long) r);
+  grub_test_assert (((a > 0) == (b > 0)) ? q >= 0 : q <= 0, "quotient sign mismatch: %lld / %lld = %lld",
+		    (long long) a, (long long) b, (long long) q);
+  grub_test_assert (abs64(r) < abs64(b), "remainder is larger than dividend: %lld %% %lld = %lld",
+		    (long long) a, (long long) b, (long long) r);
+  grub_test_assert (q * b + r == a, "division doesn't satisfy base property: 0x%llx * 0x%llx + 0x%llx != 0x%llx", (long long) q, (long long) b, (long long) r,
+		    (long long) a);
+#if GRUB_TARGET_SIZEOF_VOID_P == 8
+  grub_test_assert (q == (a / b),
+		    "C compiler division failure in 0x%llx, 0x%llx", (long long) a, (long long) b);
+  grub_test_assert (r == (a % b),
+		    "C compiler modulo failure in 0x%llx, 0x%llx", (long long) a, (long long) b);
+#endif
+}
+
+static void
+test_all(grub_uint64_t a, grub_uint64_t b)
+{
+  test64 (a, b);
+  test32 (a, b);
+  test64s (a, b);
+  test32s (a, b);
+  test64s (a, -b);
+  test32s (a, -b);
+  test64s (-a, b);
+  test32s (-a, b);
+  test64s (-a, -b);
+  test32s (-a, -b);
+}
+
 static void
 div_test (void)
 {
@@ -103,8 +171,7 @@ div_test (void)
 
   for (i = 0; i < ARRAY_SIZE (vectors); i++)
     {
-      test64 (vectors[i][0], vectors[i][1]);
-      test32 (vectors[i][0], vectors[i][1]);
+      test_all (vectors[i][0], vectors[i][1]);
     }
   for (i = 0; i < 40000; i++)
     {
@@ -114,9 +181,7 @@ div_test (void)
 	b = 1;
       if (a == 0)
 	a = 1;
-      test64 (a, b);
-      test32 (a, b);
-
+      test_all (a, b);
     }
 }
 
diff --git a/grub-core/tests/lib/functional_test.c b/grub-core/tests/lib/functional_test.c
index 5be7a58e5..d4822a124 100644
--- a/grub-core/tests/lib/functional_test.c
+++ b/grub-core/tests/lib/functional_test.c
@@ -65,6 +65,11 @@ grub_functional_all_tests (grub_extcmd_context_t ctxt __attribute__ ((unused)),
   grub_dl_load ("pbkdf2_test");
   grub_dl_load ("signature_test");
   grub_dl_load ("sleep_test");
+  grub_dl_load ("bswap_test");
+  grub_dl_load ("ctz_test");
+  grub_dl_load ("cmp_test");
+  grub_dl_load ("mul_test");
+  grub_dl_load ("shift_test");
 
   FOR_LIST_ELEMENTS (test, grub_test_list)
     ok = !grub_test_run (test) && ok;
diff --git a/grub-core/tests/mul_test.c b/grub-core/tests/mul_test.c
new file mode 100644
index 000000000..cd6423192
--- /dev/null
+++ b/grub-core/tests/mul_test.c
@@ -0,0 +1,73 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/test.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static grub_uint64_t vectors[][2] = {
+  { 0xffffffffffffffffULL, 1},
+  { 1, 0xffffffffffffffffULL},
+  { 0xffffffffffffffffULL, 0xffffffffffffffffULL},
+  { 1, 1 },
+  { 2, 1 }
+};
+
+static void
+test64(grub_uint64_t a, grub_uint64_t b)
+{
+  grub_uint64_t r1 = a * b, r2 = 0, r3;
+  int i;
+  for (i = 0; i < 64; i++)
+    if ((a & (1LL << i)))
+      r2 += b << i;
+  r3 = ((grub_int64_t) a) * ((grub_int64_t) b);
+  grub_test_assert (r1 == r2,
+		    "multiplication mismatch (u): 0x%llx x 0x%llx = 0x%llx != 0x%llx",
+		    (long long) a, (long long) b, (long long) r2, (long long) r1);
+  grub_test_assert (r3 == r2,
+		    "multiplication mismatch (s): 0x%llx x 0x%llx = 0x%llx != 0x%llx",
+		    (long long) a, (long long) b, (long long) r2, (long long) r3);
+}
+
+static void
+mul_test (void)
+{
+  grub_uint64_t a = 404, b = 7;
+  grub_size_t i;
+
+  for (i = 0; i < ARRAY_SIZE (vectors); i++)
+    {
+      test64 (vectors[i][0], vectors[i][1]);
+    }
+  for (i = 0; i < 40000; i++)
+    {
+      a = 17 * a + 13 * b;
+      b = 23 * a + 29 * b;
+      if (b == 0)
+	b = 1;
+      if (a == 0)
+	a = 1;
+      test64 (a, b);
+    }
+}
+
+/* Register example_test method as a functional test.  */
+GRUB_FUNCTIONAL_TEST (mul_test, mul_test);
diff --git a/grub-core/tests/shift_test.c b/grub-core/tests/shift_test.c
new file mode 100644
index 000000000..4120f520a
--- /dev/null
+++ b/grub-core/tests/shift_test.c
@@ -0,0 +1,157 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2015 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/test.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static grub_uint64_t vectors[] = {
+  0xffffffffffffffffULL, 1, 2, 0, 0x0102030405060708ULL
+};
+
+/* We're testing shifts, don't replace access to this with a shift.  */
+static const grub_uint8_t bitmask[] =
+  { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
+
+typedef union {
+  grub_uint64_t v64;
+  grub_uint8_t v8[8];
+} grub_raw_u64_t;
+
+static int
+get_bit64 (grub_uint64_t v, int b)
+{
+  grub_raw_u64_t vr = { .v64 = v };
+  grub_uint8_t *p = vr.v8;
+  if (b >= 64)
+    return 0;
+#ifdef GRUB_CPU_WORDS_BIGENDIAN
+  p += 7 - b / 8;
+#else
+  p += b / 8;
+#endif
+  return !!(*p & bitmask[b % 8]);
+}
+
+static grub_uint64_t
+set_bit64 (grub_uint64_t v, int b)
+{
+  grub_raw_u64_t vr = { .v64 = v };
+  grub_uint8_t *p = vr.v8;
+  if (b >= 64)
+    return v;
+#ifdef GRUB_CPU_WORDS_BIGENDIAN
+  p += 7 - b / 8;
+#else
+  p += b / 8;
+#endif
+  *p |= bitmask[b % 8];
+  return vr.v64;
+}
+
+static grub_uint64_t
+left_shift64 (grub_uint64_t v, int s)
+{
+  grub_uint64_t r = 0;
+  int i;
+  for (i = 0; i + s < 64; i++)
+    if (get_bit64 (v, i))
+      r = set_bit64 (r, i + s);
+  return r;
+}
+
+static grub_uint64_t
+right_shift64 (grub_uint64_t v, int s)
+{
+  grub_uint64_t r = 0;
+  int i;
+  for (i = s; i < 64; i++)
+    if (get_bit64 (v, i))
+      r = set_bit64 (r, i - s);
+  return r;
+}
+
+static grub_uint64_t
+arithmetic_right_shift64 (grub_uint64_t v, int s)
+{
+  grub_uint64_t r = 0;
+  int i;
+  for (i = s; i < 64; i++)
+    if (get_bit64 (v, i))
+      r = set_bit64 (r, i - s);
+  if (get_bit64 (v, 63))
+    for (i -= s; i < 64; i++)
+	r = set_bit64 (r, i);
+    
+  return r;
+}
+
+static void
+test64 (grub_uint64_t v)
+{
+  int i;
+  for (i = 0; i < 64; i++)
+    {
+      grub_test_assert ((v << i) == left_shift64 (v, i),
+			"lshift wrong: 0x%llx << %d: 0x%llx, 0x%llx",
+			(long long) v, i,
+			(long long) (v << i), (long long) left_shift64 (v, i));
+      grub_test_assert ((v >> i) == right_shift64 (v, i),
+			"rshift wrong: 0x%llx >> %d: 0x%llx, 0x%llx",
+			(long long) v, i,
+			(long long) (v >> i), (long long) right_shift64 (v, i));
+      grub_test_assert ((((grub_int64_t) v) >> i) == (grub_int64_t) arithmetic_right_shift64 (v, i),
+			"arithmetic rshift wrong: ((grub_int64_t) 0x%llx) >> %d: 0x%llx, 0x%llx",
+			(long long) v, i,
+			(long long) (((grub_int64_t) v) >> i), (long long) arithmetic_right_shift64 (v, i));
+    }
+}
+
+static void
+test_all(grub_uint64_t a)
+{
+  test64 (a);
+}
+
+static void
+shift_test (void)
+{
+  grub_uint64_t a = 404, b = 7;
+  grub_size_t i;
+
+  for (i = 0; i < ARRAY_SIZE (vectors); i++)
+    {
+      test_all (vectors[i]);
+    }
+  for (i = 0; i < 4000; i++)
+    {
+      a = 17 * a + 13 * b;
+      b = 23 * a + 29 * b;
+      if (b == 0)
+	b = 1;
+      if (a == 0)
+	a = 1;
+      test_all (a);
+      test_all (b);
+    }
+}
+
+/* Register example_test method as a functional test.  */
+GRUB_FUNCTIONAL_TEST (shift_test, shift_test);
diff --git a/grub-core/video/bitmap_scale.c b/grub-core/video/bitmap_scale.c
index 0b93d0206..70c32f029 100644
--- a/grub-core/video/bitmap_scale.c
+++ b/grub-core/video/bitmap_scale.c
@@ -361,35 +361,46 @@ scale_nn (struct grub_video_bitmap *dst, struct grub_video_bitmap *src)
   unsigned dh = dst->mode_info.height;
   unsigned sw = src->mode_info.width;
   unsigned sh = src->mode_info.height;
-  unsigned dstride = dst->mode_info.pitch;
-  unsigned sstride = src->mode_info.pitch;
+  int dstride = dst->mode_info.pitch;
+  int sstride = src->mode_info.pitch;
   /* bytes_per_pixel is the same for both src and dst. */
-  unsigned bytes_per_pixel = dst->mode_info.bytes_per_pixel;
+  int bytes_per_pixel = dst->mode_info.bytes_per_pixel;
+  unsigned dy, sy, ystep, yfrac, yover;
+  unsigned sx, xstep, xfrac, xover;
+  grub_uint8_t *dptr, *dline_end, *sline;
 
-  unsigned dy;
-  for (dy = 0; dy < dh; dy++)
+  xstep = sw / dw;
+  xover = sw % dw;
+  ystep = sh / dh;
+  yover = sh % dh;
+
+  for (dy = 0, sy = 0, yfrac = 0; dy < dh; dy++, sy += ystep, yfrac += yover)
     {
-      unsigned dx;
-      for (dx = 0; dx < dw; dx++)
+      if (yfrac >= dh)
+	{
+	  yfrac -= dh;
+	  sy++;
+	}
+      dptr = ddata + dy * dstride;
+      dline_end = dptr + dw * bytes_per_pixel;
+      sline = sdata + sy * sstride;
+      for (sx = 0, xfrac = 0; dptr < dline_end; sx += xstep, xfrac += xover, dptr += bytes_per_pixel)
         {
-          grub_uint8_t *dptr;
           grub_uint8_t *sptr;
-          unsigned sx;
-          unsigned sy;
-          unsigned comp;
+          int comp;
 
-          /* Compute the source coordinate that the destination coordinate
-             maps to.  Note: sx/sw = dx/dw  =>  sx = sw*dx/dw. */
-          sx = sw * dx / dw;
-          sy = sh * dy / dh;
+	  if (xfrac >= dw)
+	    {
+	      xfrac -= dw;
+	      sx++;
+	    }
 
           /* Get the address of the pixels in src and dst. */
-          dptr = ddata + dy * dstride + dx * bytes_per_pixel;
-          sptr = sdata + sy * sstride + sx * bytes_per_pixel;
+	  sptr = sline + sx * bytes_per_pixel;
 
-          /* Copy the pixel color value. */
-          for (comp = 0; comp < bytes_per_pixel; comp++)
-            dptr[comp] = sptr[comp];
+	  /* Copy the pixel color value. */
+	  for (comp = 0; comp < bytes_per_pixel; comp++)
+	    dptr[comp] = sptr[comp];
         }
     }
   return GRUB_ERR_NONE;
@@ -422,27 +433,40 @@ scale_bilinear (struct grub_video_bitmap *dst, struct grub_video_bitmap *src)
   int sstride = src->mode_info.pitch;
   /* bytes_per_pixel is the same for both src and dst. */
   int bytes_per_pixel = dst->mode_info.bytes_per_pixel;
+  unsigned dy, syf, sy, ystep, yfrac, yover;
+  unsigned sxf, sx, xstep, xfrac, xover;
+  grub_uint8_t *dptr, *dline_end, *sline;
 
-  unsigned dy;
-  for (dy = 0; dy < dh; dy++)
+  xstep = (sw << 8) / dw;
+  xover = (sw << 8) % dw;
+  ystep = (sh << 8) / dh;
+  yover = (sh << 8) % dh;
+
+  for (dy = 0, syf = 0, yfrac = 0; dy < dh; dy++, syf += ystep, yfrac += yover)
     {
-      unsigned dx;
-      for (dx = 0; dx < dw; dx++)
+      if (yfrac >= dh)
+	{
+	  yfrac -= dh;
+	  syf++;
+	}
+      sy = syf >> 8;
+      dptr = ddata + dy * dstride;
+      dline_end = dptr + dw * bytes_per_pixel;
+      sline = sdata + sy * sstride;
+      for (sxf = 0, xfrac = 0; dptr < dline_end; sxf += xstep, xfrac += xover, dptr += bytes_per_pixel)
         {
-          grub_uint8_t *dptr;
           grub_uint8_t *sptr;
-          unsigned sx;
-          unsigned sy;
           int comp;
 
-          /* Compute the source coordinate that the destination coordinate
-             maps to.  Note: sx/sw = dx/dw  =>  sx = sw*dx/dw. */
-          sx = sw * dx / dw;
-          sy = sh * dy / dh;
+	  if (xfrac >= dw)
+	    {
+	      xfrac -= dw;
+	      sxf++;
+	    }
 
           /* Get the address of the pixels in src and dst. */
-          dptr = ddata + dy * dstride + dx * bytes_per_pixel;
-          sptr = sdata + sy * sstride + sx * bytes_per_pixel;
+	  sx = sxf >> 8;
+	  sptr = sline + sx * bytes_per_pixel;
 
           /* If we have enough space to do so, use bilinear interpolation.
              Otherwise, fall back to nearest neighbor for this pixel. */
@@ -453,27 +477,27 @@ scale_bilinear (struct grub_video_bitmap *dst, struct grub_video_bitmap *src)
               /* Fixed-point .8 numbers representing the fraction of the
                  distance in the x (u) and y (v) direction within the
                  box of 4 pixels in the source. */
-              int u = (256 * sw * dx / dw) - (sx * 256);
-              int v = (256 * sh * dy / dh) - (sy * 256);
+              unsigned u = sxf & 0xff;
+              unsigned v = syf & 0xff;
 
               for (comp = 0; comp < bytes_per_pixel; comp++)
                 {
                   /* Get the component's values for the
                      four source corner pixels. */
-                  int f00 = sptr[comp];
-                  int f10 = sptr[comp + bytes_per_pixel];
-                  int f01 = sptr[comp + sstride];
-                  int f11 = sptr[comp + sstride + bytes_per_pixel];
+                  unsigned f00 = sptr[comp];
+                  unsigned f10 = sptr[comp + bytes_per_pixel];
+                  unsigned f01 = sptr[comp + sstride];
+                  unsigned f11 = sptr[comp + sstride + bytes_per_pixel];
 
                   /* Count coeffecients. */
-                  int c00 = (256 - u) * (256 - v);
-                  int c10 = u * (256 - v);
-                  int c01 = (256 - u) * v;
-                  int c11 = u * v;
+                  unsigned c00 = (256 - u) * (256 - v);
+                  unsigned c10 = u * (256 - v);
+                  unsigned c01 = (256 - u) * v;
+                  unsigned c11 = u * v;
 
                   /* Interpolate. */
-                  int fxy = c00 * f00 + c01 * f01 + c10 * f10 + c11 * f11;
-                  fxy = fxy / (256 * 256);
+                  unsigned fxy = c00 * f00 + c01 * f01 + c10 * f10 + c11 * f11;
+                  fxy = fxy >> 16;
 
                   dptr[comp] = fxy;
                 }
diff --git a/grub-core/video/bochs.c b/grub-core/video/bochs.c
index 9098f90d1..3bcfa53a9 100644
--- a/grub-core/video/bochs.c
+++ b/grub-core/video/bochs.c
@@ -359,6 +359,7 @@ grub_video_bochs_setup (unsigned int width, unsigned int height,
     case 32:
       framebuffer.mode_info.reserved_mask_size = 8;
       framebuffer.mode_info.reserved_field_pos = 24;
+      /* Fallthrough.  */
 
     case 24:
       framebuffer.mode_info.red_mask_size = 8;
diff --git a/grub-core/video/cirrus.c b/grub-core/video/cirrus.c
index 4913084fa..e2149e8ce 100644
--- a/grub-core/video/cirrus.c
+++ b/grub-core/video/cirrus.c
@@ -440,6 +440,7 @@ grub_video_cirrus_setup (unsigned int width, unsigned int height,
     case 32:
       framebuffer.mode_info.reserved_mask_size = 8;
       framebuffer.mode_info.reserved_field_pos = 24;
+      /* Fallthrough.  */
 
     case 24:
       framebuffer.mode_info.red_mask_size = 8;
diff --git a/grub-core/video/fb/fbblit.c b/grub-core/video/fb/fbblit.c
index 3a073cea7..d55924837 100644
--- a/grub-core/video/fb/fbblit.c
+++ b/grub-core/video/fb/fbblit.c
@@ -1145,6 +1145,20 @@ grub_video_fbblit_replace_index_RGB888 (struct grub_video_fbblit_info *dst,
     }
 }
 
+static inline grub_uint8_t
+alpha_dilute (grub_uint8_t bg, grub_uint8_t fg, grub_uint8_t alpha)
+{
+  grub_uint16_t s;
+  grub_uint16_t h, l;
+  s = (fg * alpha) + (bg * (255 ^ alpha));
+  /* Optimised division by 255.  */
+  h = s >> 8;
+  l = s & 0xff;
+  if (h + l >= 255)
+    h++;
+  return h;
+}
+
 /* Generic blending blitter.  Works for every supported format.  */
 static void
 grub_video_fbblit_blend (struct grub_video_fbblit_info *dst,
@@ -1190,12 +1204,9 @@ grub_video_fbblit_blend (struct grub_video_fbblit_info *dst,
           grub_video_fb_unmap_color_int (dst, dst_color, &dst_red,
 					 &dst_green, &dst_blue, &dst_alpha);
 
-          dst_red = (((src_red * src_alpha)
-                      + (dst_red * (255 ^ src_alpha))) / 255U);
-          dst_green = (((src_green * src_alpha)
-                        + (dst_green * (255 ^ src_alpha))) / 255U);
-          dst_blue = (((src_blue * src_alpha)
-                       + (dst_blue * (255 ^ src_alpha))) / 255U);
+          dst_red = alpha_dilute (dst_red, src_red, src_alpha);
+          dst_green = alpha_dilute (dst_green, src_green, src_alpha);
+          dst_blue = alpha_dilute (dst_blue, src_blue, src_alpha);
 
           dst_alpha = src_alpha;
           dst_color = grub_video_fb_map_rgba (dst_red, dst_green, dst_blue,
@@ -1270,11 +1281,11 @@ grub_video_fbblit_blend_BGRA8888_RGBA8888 (struct grub_video_fbblit_info *dst,
               color = *dstptr;
 
               dr = (color >> 16) & 0xFF;
-              dr = (dr * (255 ^ a) + sr * a) / 255U;
+              dr = alpha_dilute (dr, sr, a);
               dg = (color >> 8) & 0xFF;
-              dg = (dg * (255 ^ a) + sg * a) / 255U;
+              dg = alpha_dilute (dg, sg, a);
               db = (color >> 0) & 0xFF;
-              db = (db * (255 ^ a) + sb * a) / 255U;
+              db = alpha_dilute (db, sb, a);
             }
 
           color = (a << 24) | (dr << 16) | (dg << 8) | db;
@@ -1360,9 +1371,9 @@ grub_video_fbblit_blend_BGR888_RGBA8888 (struct grub_video_fbblit_info *dst,
               db = dstptr[2];
 #endif
 
-              db = (db * (255 ^ a) + sb * a) / 255U;
-              dg = (dg * (255 ^ a) + sg * a) / 255U;
-              dr = (dr * (255 ^ a) + sr * a) / 255U;
+              db = alpha_dilute (db, sb, a);
+              dg = alpha_dilute (dg, sg, a);
+              dr = alpha_dilute (dr, sr, a);
             }
 
 #ifndef GRUB_CPU_WORDS_BIGENDIAN
@@ -1440,9 +1451,9 @@ grub_video_fbblit_blend_RGBA8888_RGBA8888 (struct grub_video_fbblit_info *dst,
           dg = (color >> 8) & 0xFF;
           db = (color >> 16) & 0xFF;
 
-          dr = (dr * (255 ^ a) + sr * a) / 255U;
-          dg = (dg * (255 ^ a) + sg * a) / 255U;
-          db = (db * (255 ^ a) + sb * a) / 255U;
+          dr = alpha_dilute (dr, sr, a);
+          dg = alpha_dilute (dg, sg, a);
+          db = alpha_dilute (db, sb, a);
 
           color = (a << 24) | (db << 16) | (dg << 8) | dr;
 
@@ -1525,9 +1536,9 @@ grub_video_fbblit_blend_RGB888_RGBA8888 (struct grub_video_fbblit_info *dst,
           dr = dstptr[2];
 #endif
 
-          dr = (dr * (255 ^ a) + sr * a) / 255U;
-          dg = (dg * (255 ^ a) + sg * a) / 255U;
-          db = (db * (255 ^ a) + sb * a) / 255U;
+          dr = alpha_dilute (dr, sr, a);
+          dg = alpha_dilute (dg, sg, a);
+          db = alpha_dilute (db, sb, a);
 
 #ifndef GRUB_CPU_WORDS_BIGENDIAN
           *dstptr++ = dr;
@@ -1601,9 +1612,9 @@ grub_video_fbblit_blend_index_RGBA8888 (struct grub_video_fbblit_info *dst,
 
           grub_video_fb_unmap_color_int (dst, *dstptr, &dr, &dg, &db, &da);
 
-          dr = (dr * (255 ^ a) + sr * a) / 255U;
-          dg = (dg * (255 ^ a) + sg * a) / 255U;
-          db = (db * (255 ^ a) + sb * a) / 255U;
+          dr = alpha_dilute (dr, sr, a);
+          dg = alpha_dilute (dg, sg, a);
+          db = alpha_dilute (db, sb, a);
 
           color = grub_video_fb_map_rgb(dr, dg, db);
 
@@ -1683,9 +1694,9 @@ grub_video_fbblit_blend_XXXA8888_1bit (struct grub_video_fbblit_info *dst,
 	      grub_uint8_t d2 = (*dstptr >> 8) & 0xFF;
 	      grub_uint8_t d3 = (*dstptr >> 16) & 0xFF;
 
-	      d1 = (d1 * (255 ^ a) + s1 * a) / 255U;
-	      d2 = (d2 * (255 ^ a) + s2 * a) / 255U;
-	      d3 = (d3 * (255 ^ a) + s3 * a) / 255U;
+	      d1 = alpha_dilute (d1, s1, a);
+	      d2 = alpha_dilute (d2, s2, a);
+	      d3 = alpha_dilute (d3, s3, a);
 
 	      *dstptr = (a << 24) | (d3 << 16) | (d2 << 8) | d1;
 	    }
@@ -1791,9 +1802,9 @@ grub_video_fbblit_blend_XXX888_1bit (struct grub_video_fbblit_info *dst,
 	      grub_uint8_t d2 = (*(grub_uint32_t *) dstptr >> 8) & 0xFF;
 	      grub_uint8_t d3 = (*(grub_uint32_t *) dstptr >> 16) & 0xFF;
 
-	      ((grub_uint8_t *) dstptr)[0] = (d1 * (255 ^ a) + s1 * a) / 255U;
-	      ((grub_uint8_t *) dstptr)[1] = (d2 * (255 ^ a) + s2 * a) / 255U;
-	      ((grub_uint8_t *) dstptr)[2] = (d3 * (255 ^ a) + s3 * a) / 255U;
+	      ((grub_uint8_t *) dstptr)[0] = alpha_dilute (d1, s1, a);
+	      ((grub_uint8_t *) dstptr)[1] = alpha_dilute (d2, s2, a);
+	      ((grub_uint8_t *) dstptr)[2] = alpha_dilute (d3, s3, a);
 	    }
 
 	  srcmask >>= 1;
@@ -1887,9 +1898,9 @@ grub_video_fbblit_blend_XXX565_1bit (struct grub_video_fbblit_info *dst,
 	      grub_uint8_t d2 = (*dstptr >> 5) & 0x3F;
 	      grub_uint8_t d3 = (*dstptr >> 11) & 0x1F;
 
-	      d1 = (d1 * (255 ^ a) + s1 * a) / 255U;
-	      d2 = (d2 * (255 ^ a) + s2 * a) / 255U;
-	      d3 = (d3 * (255 ^ a) + s3 * a) / 255U;
+	      d1 = alpha_dilute (d1, s1, a);
+	      d2 = alpha_dilute (d2, s2, a);
+	      d3 = alpha_dilute (d3, s3, a);
 
 	      *dstptr = (d1 & 0x1f) | ((d2 & 0x3f) << 5) | ((d3 & 0x1f) << 11);
 	    }
diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c
index 62b5c2245..b7f911926 100644
--- a/grub-core/video/i386/pc/vbe.c
+++ b/grub-core/video/i386/pc/vbe.c
@@ -304,8 +304,7 @@ grub_vbe_bios_getset_dac_palette_width (int set, int *dac_mask_size)
   struct grub_bios_int_registers regs;
 
   regs.eax = 0x4f08;
-  regs.ebx = (*dac_mask_size & 0xff) >> 8;
-  regs.ebx = set ? 1 : 0;
+  regs.ebx = ((*dac_mask_size & 0xff) << 8) | (set ? 1 : 0);
   regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
   grub_bios_interrupt (0x10, &regs);
   *dac_mask_size = (regs.ebx >> 8) & 0xff;
@@ -875,6 +874,7 @@ vbe2videoinfo (grub_uint32_t mode,
       /* CGA is basically 4-bit packed pixel.  */
     case GRUB_VBE_MEMORY_MODEL_CGA:
       mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_CGA;
+      /* Fallthrough.  */
     case GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL:
       mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
       break;
@@ -887,6 +887,7 @@ vbe2videoinfo (grub_uint32_t mode,
       /* Non chain 4 is a special case of planar.  */
     case GRUB_VBE_MEMORY_MODEL_NONCHAIN4_256:
       mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_NONCHAIN4;
+      /* Fallthrough.  */
     case GRUB_VBE_MEMORY_MODEL_PLANAR:
       mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_PLANAR
 	| GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
index 2dc2ee10e..c3e0df240 100644
--- a/grub-core/video/readers/jpeg.c
+++ b/grub-core/video/readers/jpeg.c
@@ -94,7 +94,7 @@ struct grub_jpeg_data
   jpeg_data_unit_t crdu;
   jpeg_data_unit_t cbdu;
 
-  unsigned vs, hs;
+  unsigned log_vs, log_hs;
   int dri;
   unsigned r1;
 
@@ -315,11 +315,14 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data)
       ss = grub_jpeg_get_byte (data);	/* Sampling factor.  */
       if (!id)
 	{
-	  data->vs = ss & 0xF;	/* Vertical sampling.  */
-	  data->hs = ss >> 4;	/* Horizontal sampling.  */
-	  if ((data->vs > 2) || (data->hs > 2))
+	  grub_uint8_t vs, hs;
+	  vs = ss & 0xF;	/* Vertical sampling.  */
+	  hs = ss >> 4;	/* Horizontal sampling.  */
+	  if ((vs > 2) || (hs > 2) || (vs == 0) || (hs == 0))
 	    return grub_error (GRUB_ERR_BAD_FILE_TYPE,
 			       "jpeg: sampling method not supported");
+	  data->log_vs = (vs == 2);
+	  data->log_hs = (hs == 2);
 	}
       else if (ss != JPEG_SAMPLING_1x1)
 	return grub_error (GRUB_ERR_BAD_FILE_TYPE,
@@ -616,10 +619,10 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data)
   unsigned c1, vb, hb, nr1, nc1;
   int rst = data->dri;
 
-  vb = data->vs * 8;
-  hb = data->hs * 8;
-  nr1 = (data->image_height + vb - 1) / vb;
-  nc1 = (data->image_width + hb - 1) / hb;
+  vb = 8 << data->log_vs;
+  hb = 8 << data->log_hs;
+  nr1 = (data->image_height + vb - 1) >> (3 + data->log_vs);
+  nc1 = (data->image_width + hb - 1)  >> (3 + data->log_hs);
 
   for (; data->r1 < nr1 && (!data->dri || rst);
        data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3)
@@ -629,8 +632,8 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data)
 	unsigned r2, c2, nr2, nc2;
 	grub_uint8_t *ptr2;
 
-	for (r2 = 0; r2 < data->vs; r2++)
-	  for (c2 = 0; c2 < data->hs; c2++)
+	for (r2 = 0; r2 < (1U << data->log_vs); r2++)
+	  for (c2 = 0; c2 < (1U << data->log_hs); c2++)
 	    grub_jpeg_decode_du (data, 0, data->ydu[r2 * 2 + c2]);
 
 	if (data->color_components >= 3)
@@ -652,7 +655,7 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data)
 	      unsigned i0;
 	      int yy;
 
-	      i0 = (r2 / data->vs) * 8 + (c2 / data->hs);
+	      i0 = (r2 >> data->log_vs) * 8 + (c2 >> data->log_hs);
 	      yy = data->ydu[(r2 / 8) * 2 + (c2 / 8)][(r2 % 8) * 8 + (c2 % 8)];
 
 	      if (data->color_components >= 3)
diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
index 1f03f88d3..e1a01e99f 100644
--- a/grub-core/video/readers/png.c
+++ b/grub-core/video/readers/png.c
@@ -227,7 +227,7 @@ grub_png_decode_image_palette (struct grub_png_data *data,
 {
   unsigned i = 0, j;
 
-  if (len == 0 || len % 3 != 0)
+  if (len == 0)
     return GRUB_ERR_NONE;
 
   for (i = 0; 3 * i < len && i < 256; i++)
@@ -851,15 +851,26 @@ grub_png_convert_image (struct grub_png_data *data)
       int mask = (1 << data->color_bits) - 1;
       unsigned j;
       if (data->is_gray)
-	for (i = 0; i < (1U << data->color_bits); i++)
-	  {
-	    grub_uint8_t col = (0xff * i) / ((1U << data->color_bits) - 1);
-	    palette[i][0] = col;
-	    palette[i][1] = col;
-	    palette[i][2] = col;
-	  }
+	{
+	  /* Generic formula is
+	     (0xff * i) / ((1U << data->color_bits) - 1)
+	     but for allowed bit depth of 1, 2 and for it's
+	     equivalent to
+	     (0xff / ((1U << data->color_bits) - 1)) * i
+	     Precompute the multipliers to avoid division.
+	  */
+
+	  const grub_uint8_t multipliers[5] = { 0xff, 0xff, 0x55, 0x24, 0x11 };
+	  for (i = 0; i < (1U << data->color_bits); i++)
+	    {
+	      grub_uint8_t col = multipliers[data->color_bits] * i;
+	      palette[i][0] = col;
+	      palette[i][1] = col;
+	      palette[i][2] = col;
+	    }
+	}
       else
-	grub_memcpy (palette, data->palette, 16 * 3);
+	grub_memcpy (palette, data->palette, 3 << data->color_bits);
       d1c = d1;
       d2c = d2;
       for (j = 0; j < data->image_height; j++, d1c += data->image_width * 3,
diff --git a/include/grub/arm/reloc.h b/include/grub/arm/reloc.h
index b938037a0..ae92e21f1 100644
--- a/include/grub/arm/reloc.h
+++ b/include/grub/arm/reloc.h
@@ -43,4 +43,9 @@ void
 grub_arm_jump24_set_offset (grub_uint32_t *target,
 			    grub_int32_t offset);
 
+grub_uint16_t
+grub_arm_thm_movw_movt_get_value (grub_uint16_t *target);
+void
+grub_arm_thm_movw_movt_set_value (grub_uint16_t *target, grub_uint16_t value);
+
 #endif
diff --git a/include/grub/compiler-rt-emu.h b/include/grub/compiler-rt-emu.h
new file mode 100644
index 000000000..edc82999e
--- /dev/null
+++ b/include/grub/compiler-rt-emu.h
@@ -0,0 +1,235 @@
+/* compiler-rt-emu.h - prototypes for compiler helpers. */
+/*
+ *  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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_COMPILER_RT_HEADER
+#define GRUB_COMPILER_RT_HEADER	1
+
+#include <config-util.h>
+#include <grub/types.h>
+#include <grub/symbol.h>
+
+#ifdef HAVE___UDIVSI3
+grub_uint32_t
+EXPORT_FUNC (__udivsi3) (grub_uint32_t a, grub_uint32_t b);
+#endif
+
+#ifdef HAVE___UMODSI3
+grub_uint32_t
+EXPORT_FUNC (__umodsi3) (grub_uint32_t a, grub_uint32_t b);
+#endif
+
+#ifdef HAVE___DIVSI3
+grub_int32_t
+EXPORT_FUNC (__divsi3) (grub_int32_t a, grub_int32_t b);
+#endif
+
+#ifdef HAVE___MODSI3
+grub_int32_t
+EXPORT_FUNC (__modsi3) (grub_int32_t a, grub_int32_t b);
+#endif
+
+#ifdef HAVE___DIVDI3
+grub_int64_t
+EXPORT_FUNC (__divdi3) (grub_int64_t a, grub_int64_t b);
+#endif
+
+#ifdef HAVE___MODDI3
+grub_int64_t
+EXPORT_FUNC (__moddi3) (grub_int64_t a, grub_int64_t b);
+#endif
+
+#ifdef HAVE___UDIVDI3
+grub_uint64_t
+EXPORT_FUNC (__udivdi3) (grub_uint64_t a, grub_uint64_t b);
+#endif
+
+#ifdef HAVE___UMODDI3
+grub_uint64_t
+EXPORT_FUNC (__umoddi3) (grub_uint64_t a, grub_uint64_t b);
+#endif
+
+#ifdef HAVE___CTZDI2
+unsigned
+EXPORT_FUNC (__ctzdi2) (grub_uint64_t x);
+#endif
+
+#ifdef HAVE___CTZSI2
+unsigned
+EXPORT_FUNC (__ctzsi2) (grub_uint32_t x);
+#endif
+
+#ifdef HAVE___AEABI_UIDIV
+grub_uint32_t
+EXPORT_FUNC (__aeabi_uidiv) (grub_uint32_t a, grub_uint32_t b);
+#endif
+
+#ifdef HAVE___AEABI_UIDIVMOD
+grub_uint32_t
+EXPORT_FUNC (__aeabi_uidivmod) (grub_uint32_t a, grub_uint32_t b);
+#endif
+
+#ifdef HAVE___AEABI_IDIV
+grub_int32_t
+EXPORT_FUNC (__aeabi_idiv) (grub_int32_t a, grub_int32_t b);
+#endif
+
+#ifdef HAVE___AEABI_IDIVMOD
+grub_int32_t
+EXPORT_FUNC (__aeabi_idivmod) (grub_int32_t a, grub_int32_t b);
+#endif
+
+#ifdef HAVE___AEABI_ULCMP
+int
+EXPORT_FUNC (__aeabi_ulcmp) (grub_uint64_t a, grub_uint64_t b);
+#endif
+
+/* Needed for allowing modules to be compiled as thumb.  */
+#ifdef HAVE___MULDI3
+grub_uint64_t
+EXPORT_FUNC (__muldi3) (grub_uint64_t a, grub_uint64_t b);
+#endif
+
+#ifdef HAVE___AEABI_LMUL
+grub_uint64_t
+EXPORT_FUNC (__aeabi_lmul) (grub_uint64_t a, grub_uint64_t b);
+#endif
+
+#ifdef HAVE___AEABI_MEMCPY
+void *
+EXPORT_FUNC (__aeabi_memcpy) (void *dest, const void *src, grub_size_t n);
+#endif
+
+#ifdef HAVE___AEABI_MEMSET
+void *
+EXPORT_FUNC(__aeabi_memset) (void *s, int c, grub_size_t n);
+#endif
+
+#ifdef HAVE___AEABI_LASR
+grub_uint64_t
+EXPORT_FUNC (__aeabi_lasr) (grub_uint64_t u, int b);
+#endif
+
+#ifdef HAVE___AEABI_LLSL
+grub_uint64_t
+EXPORT_FUNC (__aeabi_llsl) (grub_uint64_t u, int b);
+#endif
+
+#ifdef HAVE___AEABI_LLSR
+grub_uint64_t
+EXPORT_FUNC (__aeabi_llsr) (grub_uint64_t u, int b);
+#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
+
+#ifdef HAVE___UCMPDI2
+int
+EXPORT_FUNC(__ucmpdi2) (grub_uint64_t a, grub_uint64_t b);
+#endif
+
+#ifdef HAVE___ASHLDI3
+grub_uint64_t
+EXPORT_FUNC(__ashldi3) (grub_uint64_t u, int b);
+#endif
+
+#ifdef HAVE___ASHRDI3
+grub_uint64_t
+EXPORT_FUNC(__ashrdi3) (grub_uint64_t u, int b);
+#endif
+
+#ifdef HAVE___LSHRDI3
+grub_uint64_t
+EXPORT_FUNC (__lshrdi3) (grub_uint64_t u, int b);
+#endif
+
+#ifdef HAVE___BSWAPSI2
+grub_uint32_t
+EXPORT_FUNC(__bswapsi2) (grub_uint32_t u);
+#endif
+
+#ifdef HAVE___BSWAPDI2
+grub_uint64_t
+EXPORT_FUNC(__bswapdi2) (grub_uint64_t u);
+#endif
+
+int EXPORT_FUNC(memcmp) (const void *s1, const void *s2, grub_size_t n);
+void *EXPORT_FUNC(memmove) (void *dest, const void *src, grub_size_t n);
+void *EXPORT_FUNC(memcpy) (void *dest, const void *src, grub_size_t n);
+void *EXPORT_FUNC(memset) (void *s, int c, grub_size_t n);
+
+#ifdef HAVE___BZERO
+void EXPORT_FUNC (__bzero) (void *s, grub_size_t n);
+#endif
+
+#ifdef HAVE___REGISTER_FRAME_INFO
+void EXPORT_FUNC (__register_frame_info) (void);
+#endif
+
+#ifdef HAVE___DEREGISTER_FRAME_INFO
+void EXPORT_FUNC (__deregister_frame_info) (void);
+#endif
+#ifdef HAVE____CHKSTK_MS
+void EXPORT_FUNC (___chkstk_ms) (void);
+#endif
+
+#ifdef HAVE___CHKSTK_MS
+void EXPORT_FUNC (__chkstk_ms) (void);
+#endif
+
+#endif
+
diff --git a/include/grub/compiler-rt.h b/include/grub/compiler-rt.h
new file mode 100644
index 000000000..9265c7e80
--- /dev/null
+++ b/include/grub/compiler-rt.h
@@ -0,0 +1,193 @@
+/* compiler-rt.h - prototypes for compiler helpers. */
+/*
+ *  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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_COMPILER_RT_HEADER
+#define GRUB_COMPILER_RT_HEADER	1
+
+#include <stdarg.h>
+#include <grub/types.h>
+#include <grub/symbol.h>
+#include <grub/misc.h>
+
+#if defined(GRUB_DIVISION_IN_SOFTWARE) && GRUB_DIVISION_IN_SOFTWARE
+
+grub_uint32_t
+EXPORT_FUNC (__udivsi3) (grub_uint32_t a, grub_uint32_t b);
+
+grub_uint32_t
+EXPORT_FUNC (__umodsi3) (grub_uint32_t a, grub_uint32_t b);
+
+grub_int32_t
+EXPORT_FUNC (__divsi3) (grub_int32_t a, grub_int32_t b);
+
+grub_int32_t
+EXPORT_FUNC (__modsi3) (grub_int32_t a, grub_int32_t b);
+
+grub_int64_t
+EXPORT_FUNC (__divdi3) (grub_int64_t a, grub_int64_t b);
+
+grub_int64_t
+EXPORT_FUNC (__moddi3) (grub_int64_t a, grub_int64_t b);
+
+grub_uint64_t
+EXPORT_FUNC (__udivdi3) (grub_uint64_t a, grub_uint64_t b);
+
+grub_uint64_t
+EXPORT_FUNC (__umoddi3) (grub_uint64_t a, grub_uint64_t b);
+
+#endif
+
+#if defined (__sparc__) || defined (__powerpc__) || defined (__mips__) || defined (__arm__)
+unsigned
+EXPORT_FUNC (__ctzdi2) (grub_uint64_t x);
+#define NEED_CTZDI2 1
+#endif
+
+#if defined (__mips__) || defined (__arm__)
+unsigned
+EXPORT_FUNC (__ctzsi2) (grub_uint32_t x);
+#define NEED_CTZSI2 1
+#endif
+
+#ifdef __arm__
+grub_uint32_t
+EXPORT_FUNC (__aeabi_uidiv) (grub_uint32_t a, grub_uint32_t b);
+grub_uint32_t
+EXPORT_FUNC (__aeabi_uidivmod) (grub_uint32_t a, grub_uint32_t b);
+
+grub_int32_t
+EXPORT_FUNC (__aeabi_idiv) (grub_int32_t a, grub_int32_t b);
+grub_int32_t
+EXPORT_FUNC (__aeabi_idivmod) (grub_int32_t a, grub_int32_t b);
+
+int
+EXPORT_FUNC (__aeabi_ulcmp) (grub_uint64_t a, grub_uint64_t b);
+
+/* Needed for allowing modules to be compiled as thumb.  */
+grub_uint64_t
+EXPORT_FUNC (__muldi3) (grub_uint64_t a, grub_uint64_t b);
+grub_uint64_t
+EXPORT_FUNC (__aeabi_lmul) (grub_uint64_t a, grub_uint64_t b);
+
+void *
+EXPORT_FUNC (__aeabi_memcpy) (void *dest, const void *src, grub_size_t n);
+void *
+EXPORT_FUNC(__aeabi_memset) (void *s, int c, grub_size_t n);
+
+grub_uint64_t
+EXPORT_FUNC (__aeabi_lasr) (grub_uint64_t u, int b);
+
+grub_uint64_t
+EXPORT_FUNC (__aeabi_llsl) (grub_uint64_t u, int b);
+
+grub_uint64_t
+EXPORT_FUNC (__aeabi_llsr) (grub_uint64_t u, int b);
+
+#endif
+
+
+#if defined (__powerpc__)
+
+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 (__powerpc__) || defined(__mips__) || defined (__arm__)
+
+int
+EXPORT_FUNC(__ucmpdi2) (grub_uint64_t a, grub_uint64_t b);
+
+grub_uint64_t
+EXPORT_FUNC(__ashldi3) (grub_uint64_t u, int b);
+
+grub_uint64_t
+EXPORT_FUNC(__ashrdi3) (grub_uint64_t u, int b);
+
+grub_uint64_t
+EXPORT_FUNC (__lshrdi3) (grub_uint64_t u, int b);
+#endif
+
+#if defined (__powerpc__) || defined(__mips__) || defined(__sparc__) || defined (__arm__)
+grub_uint32_t
+EXPORT_FUNC(__bswapsi2) (grub_uint32_t u);
+
+grub_uint64_t
+EXPORT_FUNC(__bswapdi2) (grub_uint64_t u);
+#endif
+
+#if defined (__APPLE__) && defined(__i386__)
+#define GRUB_BUILTIN_ATTR  __attribute__ ((regparm(0)))
+#else
+#define GRUB_BUILTIN_ATTR
+#endif
+
+/* Prototypes for aliases.  */
+int GRUB_BUILTIN_ATTR EXPORT_FUNC(memcmp) (const void *s1, const void *s2, grub_size_t n);
+void *GRUB_BUILTIN_ATTR EXPORT_FUNC(memmove) (void *dest, const void *src, grub_size_t n);
+void *GRUB_BUILTIN_ATTR EXPORT_FUNC(memcpy) (void *dest, const void *src, grub_size_t n);
+void *GRUB_BUILTIN_ATTR EXPORT_FUNC(memset) (void *s, int c, grub_size_t n);
+
+#ifdef __APPLE__
+void GRUB_BUILTIN_ATTR EXPORT_FUNC (__bzero) (void *s, grub_size_t n);
+#endif
+
+#if defined (__MINGW32__) || defined (__CYGWIN__)
+void EXPORT_FUNC (__register_frame_info) (void);
+void EXPORT_FUNC (__deregister_frame_info) (void);
+void EXPORT_FUNC (___chkstk_ms) (void);
+void EXPORT_FUNC (__chkstk_ms) (void);
+#endif
+
+#endif
+
diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h
index a588ba21d..df6085bcb 100644
--- a/include/grub/emu/misc.h
+++ b/include/grub/emu/misc.h
@@ -27,6 +27,7 @@
 #include <grub/symbol.h>
 #include <grub/types.h>
 #include <grub/misc.h>
+#include <grub/util/misc.h>
 
 extern int verbosity;
 extern const char *program_name;
@@ -61,8 +62,6 @@ void EXPORT_FUNC(grub_util_error) (const char *fmt, ...) __attribute__ ((format
 
 grub_uint64_t EXPORT_FUNC (grub_util_get_cpu_time_ms) (void);
 
-extern char * canonicalize_file_name (const char *path);
-
 #ifdef HAVE_DEVICE_MAPPER
 int grub_device_mapper_supported (void);
 #endif
diff --git a/include/grub/hfsplus.h b/include/grub/hfsplus.h
index 8ba8f3246..117740ae2 100644
--- a/include/grub/hfsplus.h
+++ b/include/grub/hfsplus.h
@@ -171,7 +171,7 @@ struct grub_hfsplus_catkey
   grub_uint16_t keylen;
   grub_uint32_t parent;
   grub_uint16_t namelen;
-  grub_uint16_t name[30];
+  grub_uint16_t name[0];
 } GRUB_PACKED;
 
 /* The on disk layout of an extent overflow file key.  */
@@ -207,12 +207,14 @@ struct grub_hfsplus_btnode
 
 /* Return the offset of the record with the index INDEX, in the node
    NODE which is part of the B+ tree BTREE.  */
-static inline grub_off_t
+static inline grub_uint16_t
 grub_hfsplus_btree_recoffset (struct grub_hfsplus_btree *btree,
-			   struct grub_hfsplus_btnode *node, int index)
+			   struct grub_hfsplus_btnode *node, unsigned index)
 {
   char *cnode = (char *) node;
   void *recptr;
+  if (btree->nodesize < index * sizeof (grub_uint16_t) + 2)
+    index = 0;
   recptr = (&cnode[btree->nodesize - index * sizeof (grub_uint16_t) - 2]);
   return grub_be_to_cpu16 (grub_get_unaligned16 (recptr));
 }
@@ -221,11 +223,13 @@ grub_hfsplus_btree_recoffset (struct grub_hfsplus_btree *btree,
    NODE which is part of the B+ tree BTREE.  */
 static inline struct grub_hfsplus_key *
 grub_hfsplus_btree_recptr (struct grub_hfsplus_btree *btree,
-			   struct grub_hfsplus_btnode *node, int index)
+			   struct grub_hfsplus_btnode *node, unsigned index)
 {
   char *cnode = (char *) node;
-  grub_off_t offset;
+  grub_uint16_t offset;
   offset = grub_hfsplus_btree_recoffset (btree, node, index);
+  if (offset > btree->nodesize - sizeof (struct grub_hfsplus_key))
+    offset = 0;
   return (struct grub_hfsplus_key *) &cnode[offset];
 }
 
diff --git a/include/grub/ieee1275/ofdisk.h b/include/grub/ieee1275/ofdisk.h
index 3f5831787..2f69e3f19 100644
--- a/include/grub/ieee1275/ofdisk.h
+++ b/include/grub/ieee1275/ofdisk.h
@@ -22,7 +22,4 @@
 extern void grub_ofdisk_init (void);
 extern void grub_ofdisk_fini (void);
 
-extern grub_err_t grub_ofdisk_get_block_size (const char *device,
-                                              grub_uint32_t *block_size);
-
 #endif /* ! GRUB_INIT_HEADER */
diff --git a/include/grub/libgcc.h b/include/grub/libgcc.h
deleted file mode 100644
index 8e93b6792..000000000
--- a/include/grub/libgcc.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2004,2007,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 <http://www.gnu.org/licenses/>.
- */
-
-/* We need to include config-util.h.in for HAVE_*.  */
-#ifndef __STDC_VERSION__
-#define __STDC_VERSION__ 0
-#endif
-#include <config-util.h>
-
-/* 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);
-void EXPORT_FUNC (__aeabi_llsr) (void);
-void EXPORT_FUNC (__aeabi_ulcmp) (void);
-#endif
diff --git a/include/grub/libusb.h b/include/grub/libusb.h
deleted file mode 100644
index 26548bccb..000000000
--- a/include/grub/libusb.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 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 <http://www.gnu.org/licenses/>.
- */
-
-void EXPORT_FUNC (usb_bulk_write) (void);
-void EXPORT_FUNC (usb_find_busses) (void);
-void EXPORT_FUNC (usb_init) (void);
-void EXPORT_FUNC (usb_find_devices) (void);
-void EXPORT_FUNC (usb_open) (void);
-void EXPORT_FUNC (usb_get_busses) (void);
-void EXPORT_FUNC (usb_control_msg) (void);
-void EXPORT_FUNC (usb_release_interface) (void);
-void EXPORT_FUNC (usb_close) (void);
-void EXPORT_FUNC (usb_bulk_read) (void);
-void EXPORT_FUNC (usb_claim_interface) (void);
diff --git a/include/grub/mips/kernel.h b/include/grub/mips/kernel.h
index 07b08848d..d0e09ddc6 100644
--- a/include/grub/mips/kernel.h
+++ b/include/grub/mips/kernel.h
@@ -21,4 +21,8 @@
 
 #include <grub/symbol.h>
 
+#ifdef ASM_FILE
+#define mips_attributes .gnu_attribute 4, 3
+#endif
+
 #endif /* ! GRUB_KERNEL_MACHINE_HEADER */
diff --git a/include/grub/misc.h b/include/grub/misc.h
index c6cd4564d..2a9f87cc2 100644
--- a/include/grub/misc.h
+++ b/include/grub/misc.h
@@ -71,12 +71,6 @@ grub_memcpy (void *dest, const void *src, grub_size_t n)
   return grub_memmove (dest, src, n);
 }
 
-#if defined (__APPLE__) && defined(__i386__) && !defined (GRUB_UTIL)
-#define GRUB_BUILTIN_ATTR  __attribute__ ((regparm(0)))
-#else
-#define GRUB_BUILTIN_ATTR
-#endif
-
 #if defined(__x86_64__) && !defined (GRUB_UTIL)
 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (__MINGW64__)
 #define GRUB_ASM_ATTR __attribute__ ((sysv_abi))
@@ -85,19 +79,6 @@ grub_memcpy (void *dest, const void *src, grub_size_t n)
 #endif
 #endif
 
-/* Prototypes for aliases.  */
-#ifndef GRUB_UTIL
-int GRUB_BUILTIN_ATTR EXPORT_FUNC(memcmp) (const void *s1, const void *s2, grub_size_t n);
-void *GRUB_BUILTIN_ATTR EXPORT_FUNC(memmove) (void *dest, const void *src, grub_size_t n);
-void *GRUB_BUILTIN_ATTR EXPORT_FUNC(memcpy) (void *dest, const void *src, grub_size_t n);
-void *GRUB_BUILTIN_ATTR EXPORT_FUNC(memset) (void *s, int c, grub_size_t n);
-
-#ifdef __APPLE__
-void GRUB_BUILTIN_ATTR EXPORT_FUNC (__bzero) (void *s, grub_size_t n);
-#endif
-
-#endif
-
 int EXPORT_FUNC(grub_memcmp) (const void *s1, const void *s2, grub_size_t n);
 int EXPORT_FUNC(grub_strcmp) (const char *s1, const char *s2);
 int EXPORT_FUNC(grub_strncmp) (const char *s1, const char *s2, grub_size_t n);
@@ -358,13 +339,37 @@ grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n,
 					  grub_uint64_t d,
 					  grub_uint64_t *r);
 
-#if (defined (__MINGW32__) || defined (__CYGWIN__)) && !defined(GRUB_UTIL)
-void EXPORT_FUNC (__register_frame_info) (void);
-void EXPORT_FUNC (__deregister_frame_info) (void);
-void EXPORT_FUNC (___chkstk_ms) (void);
-void EXPORT_FUNC (__chkstk_ms) (void);
+/* Must match softdiv group in gentpl.py.  */
+#if !defined(GRUB_MACHINE_EMU) && (defined(__arm__) || defined(__ia64__))
+#define GRUB_DIVISION_IN_SOFTWARE 1
+#else
+#define GRUB_DIVISION_IN_SOFTWARE 0
 #endif
 
+/* Some division functions need to be in kernel if compiler generates calls
+   to them. Otherwise we still need them for consistent tests but they go
+   into a separate module.  */
+#if GRUB_DIVISION_IN_SOFTWARE
+#define EXPORT_FUNC_IF_SOFTDIV EXPORT_FUNC
+#else
+#define EXPORT_FUNC_IF_SOFTDIV(x) x
+#endif
+
+grub_int64_t
+EXPORT_FUNC_IF_SOFTDIV(grub_divmod64s) (grub_int64_t n,
+					grub_int64_t d,
+					grub_int64_t *r);
+
+grub_uint32_t
+EXPORT_FUNC_IF_SOFTDIV (grub_divmod32) (grub_uint32_t n,
+					grub_uint32_t d,
+					grub_uint32_t *r);
+
+grub_int32_t
+EXPORT_FUNC_IF_SOFTDIV (grub_divmod32s) (grub_int32_t n,
+					 grub_int32_t d,
+					 grub_int32_t *r);
+
 /* Inline functions.  */
 
 static inline char *
@@ -390,13 +395,6 @@ grub_abs (int x)
     return (unsigned int) x;
 }
 
-/* Rounded-up division */
-static inline unsigned int
-grub_div_roundup (unsigned int x, unsigned int y)
-{
-  return (x + y - 1) / y;
-}
-
 /* Reboot the machine.  */
 #if defined (GRUB_MACHINE_EMU) || defined (GRUB_MACHINE_QEMU_MIPS)
 void EXPORT_FUNC(grub_reboot) (void) __attribute__ ((noreturn));
@@ -440,57 +438,6 @@ grub_error_load (const struct grub_error_saved *save)
   grub_errno = save->grub_errno;
 }
 
-#ifndef GRUB_UTIL
-
-#if defined (__arm__)
-
-grub_uint32_t
-EXPORT_FUNC (__udivsi3) (grub_uint32_t a, grub_uint32_t b);
-
-grub_uint32_t
-EXPORT_FUNC (__umodsi3) (grub_uint32_t a, grub_uint32_t b);
-
-#endif
-
-#if defined (__sparc__) || defined (__powerpc__)
-unsigned
-EXPORT_FUNC (__ctzdi2) (grub_uint64_t x);
-#define NEED_CTZDI2 1
-#endif
-
-#if defined (__mips__) || defined (__arm__)
-unsigned
-EXPORT_FUNC (__ctzsi2) (grub_uint32_t x);
-#define NEED_CTZSI2 1
-#endif
-
-#ifdef __arm__
-grub_uint32_t
-EXPORT_FUNC (__aeabi_uidiv) (grub_uint32_t a, grub_uint32_t b);
-grub_uint32_t
-EXPORT_FUNC (__aeabi_uidivmod) (grub_uint32_t a, grub_uint32_t b);
-
-/* Needed for allowing modules to be compiled as thumb.  */
-grub_uint64_t
-EXPORT_FUNC (__muldi3) (grub_uint64_t a, grub_uint64_t b);
-grub_uint64_t
-EXPORT_FUNC (__aeabi_lmul) (grub_uint64_t a, grub_uint64_t b);
-
-#endif
-
-#if defined (__ia64__)
-
-grub_uint64_t
-EXPORT_FUNC (__udivdi3) (grub_uint64_t a, grub_uint64_t b);
-
-grub_uint64_t
-EXPORT_FUNC (__umoddi3) (grub_uint64_t a, grub_uint64_t b);
-
-#endif
-
-#endif /* GRUB_UTIL */
-
-
 #if BOOT_TIME_STATS
 struct grub_boot_time
 {
diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h
index 7a8e61479..dcceaa568 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/include/grub/net/netbuff.h b/include/grub/net/netbuff.h
index 9ac168c89..1177c1220 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/include/grub/term.h b/include/grub/term.h
index 98c68a5ab..5ffb38f69 100644
--- a/include/grub/term.h
+++ b/include/grub/term.h
@@ -334,12 +334,12 @@ void grub_term_restore_pos (struct grub_term_coordinate *pos);
 
 static inline unsigned grub_term_width (struct grub_term_output *term)
 {
-  return term->getwh(term).x;
+  return term->getwh(term).x ? : 80;
 }
 
 static inline unsigned grub_term_height (struct grub_term_output *term)
 {
-  return term->getwh(term).y;
+  return term->getwh(term).y ? : 24;
 }
 
 static inline struct grub_term_coordinate
diff --git a/include/grub/types.h b/include/grub/types.h
index 79f765c62..e732efb5c 100644
--- a/include/grub/types.h
+++ b/include/grub/types.h
@@ -179,7 +179,7 @@ static inline grub_uint16_t grub_swap_bytes16(grub_uint16_t _x)
                     | (_x >> 56)); \
 })
 
-#if defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3)
+#if (defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3)) || defined(__clang__)
 static inline grub_uint32_t grub_swap_bytes32(grub_uint32_t x)
 {
 	return __builtin_bswap32(x);
diff --git a/include/grub/util/misc.h b/include/grub/util/misc.h
index 192874d42..e9e0a6724 100644
--- a/include/grub/util/misc.h
+++ b/include/grub/util/misc.h
@@ -41,7 +41,7 @@ void grub_util_write_image_at (const void *img, size_t size, off_t offset,
 
 char *make_system_path_relative_to_its_root (const char *path);
 
-char *canonicalize_file_name (const char *path);
+char *grub_canonicalize_file_name (const char *path);
 
 void grub_util_init_nls (void);
 
diff --git a/include/grub/xen.h b/include/grub/xen.h
index 6035d1a10..9ba3b8e6b 100644
--- a/include/grub/xen.h
+++ b/include/grub/xen.h
@@ -21,6 +21,8 @@
 
 #define __XEN_INTERFACE_VERSION__ 0x0003020a
 
+#define memset grub_memset
+
 #ifdef ASM_FILE
 #define __ASSEMBLY__
 #include <xen/xen.h>
diff --git a/m4/extern-inline.m4 b/m4/extern-inline.m4
index 0152f2932..e74339a16 100644
--- a/m4/extern-inline.m4
+++ b/m4/extern-inline.m4
@@ -1,6 +1,6 @@
 dnl 'extern inline' a la ISO C99.
 
-dnl Copyright 2012-2013 Free Software Foundation, Inc.
+dnl Copyright 2012-2015 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.
@@ -8,42 +8,77 @@ dnl with or without modifications, as long as this notice is preserved.
 AC_DEFUN([gl_EXTERN_INLINE],
 [
   AH_VERBATIM([extern_inline],
-[/* _GL_INLINE is a portable alternative to ISO C99 plain 'inline'.
-   _GL_EXTERN_INLINE is a portable alternative to 'extern inline'.
-   _GL_INLINE_HEADER_BEGIN contains useful stuff to put
-     in an include file, before uses of _GL_INLINE.
-     It suppresses GCC's bogus "no previous prototype for 'FOO'" diagnostic,
-     when FOO is an inline function in the header; see
-     <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54113>.
-   _GL_INLINE_HEADER_END contains useful stuff to put
-     in the same include file, after uses of _GL_INLINE.
+[/* Please see the Gnulib manual for how to use these macros.
 
    Suppress extern inline with HP-UX cc, as it appears to be broken; see
    <http://lists.gnu.org/archive/html/bug-texinfo/2013-02/msg00030.html>.
 
-   Suppress the use of extern inline on Apple's platforms,
-   as Libc-825.25 (2012-09-19) is incompatible with it; see
-   <http://lists.gnu.org/archive/html/bug-gnulib/2012-12/msg00023.html>.
-   Perhaps Apple will fix this some day.  */
+   Suppress extern inline with Sun C in standards-conformance mode, as it
+   mishandles inline functions that call each other.  E.g., for 'inline void f
+   (void) { } inline void g (void) { f (); }', c99 incorrectly complains
+   'reference to static identifier "f" in extern inline function'.
+   This bug was observed with Sun C 5.12 SunOS_i386 2011/11/16.
+
+   Suppress extern inline (with or without __attribute__ ((__gnu_inline__)))
+   on configurations that mistakenly use 'static inline' to implement
+   functions or macros in standard C headers like <ctype.h>.  For example,
+   if isdigit is mistakenly implemented via a static inline function,
+   a program containing an extern inline function that calls isdigit
+   may not work since the C standard prohibits extern inline functions
+   from calling static functions.  This bug is known to occur on:
+
+     OS X 10.8 and earlier; see:
+     http://lists.gnu.org/archive/html/bug-gnulib/2012-12/msg00023.html
+
+     DragonFly; see
+     http://muscles.dragonflybsd.org/bulk/bleeding-edge-potential/latest-per-pkg/ah-tty-0.3.12.log
+
+     FreeBSD; see:
+     http://lists.gnu.org/archive/html/bug-gnulib/2014-07/msg00104.html
+
+   OS X 10.9 has a macro __header_inline indicating the bug is fixed for C and
+   for clang but remains for g++; see <http://trac.macports.org/ticket/41033>.
+   Assume DragonFly and FreeBSD will be similar.  */
+#if (((defined __APPLE__ && defined __MACH__) \
+      || defined __DragonFly__ || defined __FreeBSD__) \
+     && (defined __header_inline \
+         ? (defined __cplusplus && defined __GNUC_STDC_INLINE__ \
+            && ! defined __clang__) \
+         : ((! defined _DONT_USE_CTYPE_INLINE_ \
+             && (defined __GNUC__ || defined __cplusplus)) \
+            || (defined _FORTIFY_SOURCE && 0 < _FORTIFY_SOURCE \
+                && defined __GNUC__ && ! defined __cplusplus))))
+# define _GL_EXTERN_INLINE_STDHEADER_BUG
+#endif
 #if ((__GNUC__ \
       ? defined __GNUC_STDC_INLINE__ && __GNUC_STDC_INLINE__ \
-      : 199901L <= __STDC_VERSION__ && !defined __HP_cc) \
-     && !defined __APPLE__)
+      : (199901L <= __STDC_VERSION__ \
+         && !defined __HP_cc \
+         && !(defined __SUNPRO_C && __STDC__))) \
+     && !defined _GL_EXTERN_INLINE_STDHEADER_BUG)
 # define _GL_INLINE inline
 # define _GL_EXTERN_INLINE extern inline
-#elif 2 < __GNUC__ + (7 <= __GNUC_MINOR__) && !defined __APPLE__
-# if __GNUC_GNU_INLINE__
+# define _GL_EXTERN_INLINE_IN_USE
+#elif (2 < __GNUC__ + (7 <= __GNUC_MINOR__) && !defined __STRICT_ANSI__ \
+       && !defined _GL_EXTERN_INLINE_STDHEADER_BUG)
+# if defined __GNUC_GNU_INLINE__ && __GNUC_GNU_INLINE__
    /* __gnu_inline__ suppresses a GCC 4.2 diagnostic.  */
 #  define _GL_INLINE extern inline __attribute__ ((__gnu_inline__))
 # else
 #  define _GL_INLINE extern inline
 # endif
 # define _GL_EXTERN_INLINE extern
+# define _GL_EXTERN_INLINE_IN_USE
 #else
 # define _GL_INLINE static _GL_UNUSED
 # define _GL_EXTERN_INLINE static _GL_UNUSED
 #endif
 
+/* In GCC, suppress bogus "no previous prototype for 'FOO'"
+   and "no previous declaration for 'FOO'" diagnostics,
+   when FOO is an inline function in the header; see
+   <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54113> and
+   <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63877>.  */
 #if 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
 # if defined __GNUC_STDC_INLINE__ && __GNUC_STDC_INLINE__
 #  define _GL_INLINE_HEADER_CONST_PRAGMA
diff --git a/po/exclude.pot b/po/exclude.pot
index 1659eb01b..ab52e9990 100644
--- a/po/exclude.pot
+++ b/po/exclude.pot
@@ -2296,10 +2296,6 @@ msgstr ""
 msgid "WEEKDAY"
 msgstr ""
 
-#: grub-core/io/lzopio.c:30
-msgid "�LZO"
-msgstr ""
-
 #: grub-core/kern/dl.c:412
 msgid "grub_mod_init"
 msgstr ""
@@ -4215,22 +4211,10 @@ msgstr ""
 msgid "ext*"
 msgstr ""
 
-#: grub-core/partmap/msdos.c:74
-msgid "�A��"
-msgstr ""
-
-#: grub-core/partmap/msdos.c:80
-msgid "�A��"
-msgstr ""
-
 #: grub-core/partmap/msdos.c:86
 msgid "HP Backup and Recovery Manager (?)"
 msgstr ""
 
-#: grub-core/partmap/msdos.c:87
-msgid "p�]F5���=���U>�"
-msgstr ""
-
 #: grub-core/partmap/msdos.c:94
 msgid "ycgl"
 msgstr ""
@@ -4574,10 +4558,6 @@ msgstr ""
 msgid " failed: %ld\n"
 msgstr ""
 
-#: grub-core/lib/xzembed/xz_stream.h:35
-msgid "�7zXZ"
-msgstr ""
-
 #: grub-core/lib/xzembed/xz_stream.h:38
 msgid "YZ"
 msgstr ""
@@ -7173,3 +7153,294 @@ msgstr ""
 #: util/grub-mkimagexx.c:845
 msgid "CALL26 Relocation out of range"
 msgstr ""
+
+#: grub-core/commands/verify.c:313
+msgid "\x99"
+msgstr ""
+
+#: grub-core/commands/videotest.c:122
+msgid "Unicode test: happy\xE2\x98\xBA \xC2\xA3 5.00"
+      " \xC2\xA1\xCF\x84\xC3\xA4u! "
+      " \xE2\x84\xA4\xE2\x8A\x86\xE2\x84\x9D"
+msgstr ""
+
+#: grub-core/disk/luks.c:40
+msgid "LUKS\xBA\xBE"
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:67 grub-core/disk/lvmparse.c:69
+msgid " = ["
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:115 grub-core/disk/lvmparse.c:123
+#: grub-core/disk/lvmparse.c:167 grub-core/disk/lvmparse.c:170
+msgid "id = \""
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:127
+msgid "extent_size = "
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:143 grub-core/disk/lvmparse.c:146
+msgid "physical_volumes {"
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:174
+msgid "pe_start = "
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:199
+msgid "logical_volumes"
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:202
+msgid "logical_volumes = "
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:226 grub-core/disk/lvmparse.c:227
+msgid "status"
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:226
+msgid "VISIBLE"
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:227
+msgid "PVMOVE"
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:228
+msgid "segment_count = "
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:246
+msgid "segment"
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:255
+msgid "start_extent = "
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:263
+msgid "extent_count = "
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:272 grub-core/disk/lvmparse.c:275
+msgid "type = \""
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:277 grub-core/disk/lvmparse.c:278
+msgid "striped\""
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:282
+msgid "stripe_count = "
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:292 grub-core/disk/lvmparse.c:396
+msgid "stripe_size = "
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:299 grub-core/disk/lvmparse.c:307
+msgid "stripes = ["
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:332
+msgid "mirror\""
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:336
+msgid "mirror_count = "
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:350 grub-core/disk/lvmparse.c:358
+msgid "mirrors = ["
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:375 grub-core/disk/lvmparse.c:376
+#: grub-core/disk/lvmparse.c:377 grub-core/disk/lvmparse.c:384
+msgid "raid"
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:378
+msgid "raidX"
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:386
+msgid "device_count = "
+msgstr ""
+
+#: grub-core/disk/lvmparse.c:410 grub-core/disk/lvmparse.c:418
+msgid "raids = ["
+msgstr ""
+
+#: grub-core/fs/cpio.c:24
+msgid "\xc7\x71"
+msgstr ""
+
+#: grub-core/fs/cpio_be.c:23
+msgid "\x71\xc7"
+msgstr ""
+
+#: grub-core/gfxmenu/gui_circular_progress.c:244
+msgid "\xc2\xb0"
+msgstr ""
+
+#: grub-core/kern/ieee1275/cmain.c:88
+msgid "IBM pSeries (emulated by qemu)"
+msgstr ""
+
+#: grub-core/lib/all_video.c:36
+msgid "/video.lst"
+msgstr ""
+
+#: grub-core/osdep/unix/config.c:108
+#, c-format
+msgid ""
+"'; printf \"GRUB_ENABLE_CRYPTODISK=%s\\nGRUB_DISTRIBUTOR=%s\\n\" "
+"\"$GRUB_ENABLE_CRYPTODISK\" \"$GRUB_DISTRIBUTOR\""
+msgstr ""
+
+#: include/grub/dl.h:141
+msgid "license"
+msgstr ""
+
+#: util/grub-install.c:1106
+msgid "BOOTAA64.EFI"
+msgstr ""
+
+#: util/grub-install.c:1133
+msgid "grubaa64.efi"
+msgstr ""
+
+#: util/grub-install.c:1274
+msgid "GRUB_ENABLE_CRYPTODISK=y"
+msgstr ""
+
+#: util/grub-mkrescue.c:656
+msgid "part_gpt"
+msgstr ""
+
+#: util/grub-mkrescue.c:657
+msgid "part_msdos"
+msgstr ""
+
+#: util/grub-mkrescue.c:663 util/grub-mkrescue.c:668 util/grub-mkrescue.c:723
+msgid "part_apple"
+msgstr ""
+
+#: util/grub-mkrescue.c:677
+msgid "bootaa64.efi"
+msgstr ""
+
+#: util/grub-probe.c:136 util/grub-probe.c:151 util/grub-probe.c:190
+#: util/grub-probe.c:247
+#, c-format
+msgid "%s%c"
+msgstr ""
+
+#: util/grub-probe.c:233
+#, c-format
+msgid "lvm%c"
+msgstr ""
+
+#: util/grub-probe.c:237
+#, c-format
+msgid "ldm%c"
+msgstr ""
+
+#: util/grub-probe.c:245
+#, c-format
+msgid "diskfilter%c"
+msgstr ""
+
+#: util/grub-probe.c:250
+#, c-format
+msgid "raid5rec%c"
+msgstr ""
+
+#: util/grub-probe.c:252
+#, c-format
+msgid "raid6rec%c"
+msgstr ""
+
+#: util/grub-mkrescue.c:136
+#, c-format
+msgid "%s\n\n%s\n\n%s"
+msgstr ""
+
+#: grub-core/kern/arm/cache.c:133
+msgid "couldn't get memory map, not enabling caches"
+msgstr ""
+
+#: grub-core/kern/arm/cache.c:149
+#, c-format
+msgid "%d crossers\n"
+msgstr ""
+
+#: grub-core/kern/arm/cache.c:154
+msgid "couldn't allocate place for MMU table, not enabling caches"
+msgstr ""
+
+#: grub-core/kern/arm/cache.c:212
+msgid "MMU tables generated\n"
+msgstr ""
+
+#: grub-core/kern/arm/cache.c:216
+msgid "enabling MMU\n"
+msgstr ""
+
+#: grub-core/kern/arm/cache.c:218
+msgid "MMU enabled\n"
+msgstr ""
+
+#: grub-core/commands/verify.c:313
+msgid "™"
+msgstr ""
+
+#: grub-core/commands/videotest.c:122
+msgid "Unicode test: happy☺ £ 5.00 ¡τäu!  ℤ⊆ℝ"
+msgstr ""
+
+#: grub-core/disk/luks.c:40
+msgid "LUKSº¾"
+msgstr ""
+
+#: grub-core/fs/cpio.c:24
+msgid "Çq"
+msgstr ""
+
+#: grub-core/fs/cpio_be.c:23
+msgid "qÇ"
+msgstr ""
+
+#: grub-core/gfxmenu/gui_circular_progress.c:244
+msgid "°"
+msgstr ""
+
+#: grub-core/lib/xzembed/xz_stream.h:35
+msgid "ý7zXZ"
+msgstr ""
+
+#: grub-core/partmap/msdos.c:74
+msgid "ÔA õ"
+msgstr ""
+
+#: grub-core/partmap/msdos.c:80
+msgid "ØA õ"
+msgstr ""
+
+#: grub-core/partmap/msdos.c:87
+msgid "pŠ]F5Å“®=†ý±U>à"
+msgstr ""
+
+#: grub-core/io/lzopio.c:30
+msgid ""
+"‰LZO\n"
+"\n"
+msgstr ""
+
+#: util/grub-probe.c:735
+#, c-format
+msgid "%s\n%s %s %s"
+msgstr ""
diff --git a/tests/ext234_test.in b/tests/ext234_test.in
index 8910b716f..c986960a8 100644
--- a/tests/ext234_test.in
+++ b/tests/ext234_test.in
@@ -29,3 +29,4 @@ fi
 "@builddir@/grub-fs-tester" ext2
 "@builddir@/grub-fs-tester" ext3
 "@builddir@/grub-fs-tester" ext4
+"@builddir@/grub-fs-tester" ext4_metabg
diff --git a/tests/fddboot_test.in b/tests/fddboot_test.in
index a05eb3e75..a59645b7f 100644
--- a/tests/fddboot_test.in
+++ b/tests/fddboot_test.in
@@ -46,6 +46,6 @@ case "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" in
 	exit 0;;
 esac
 
-if [ "$(echo hello | "${grubshell}" --boot=fd --mkrescue-arg="--compress=xz --fonts= --locales= --themes=")" != "Hello World" ]; then
+if [ "$(echo hello | "${grubshell}" --boot=fd --mkrescue-arg="--compress=xz --fonts= --locales= --themes= -no-pad")" != "Hello World" ]; then
    exit 1
 fi
diff --git a/tests/file_filter/file b/tests/file_filter/file
new file mode 100644
index 000000000..64650ac58
--- /dev/null
+++ b/tests/file_filter/file
@@ -0,0 +1 @@
+Hello, user!
diff --git a/tests/file_filter/file.gz b/tests/file_filter/file.gz
new file mode 100644
index 000000000..a07ffcbe0
Binary files /dev/null and b/tests/file_filter/file.gz differ
diff --git a/tests/file_filter/file.gz.sig b/tests/file_filter/file.gz.sig
new file mode 100644
index 000000000..602e6187e
Binary files /dev/null and b/tests/file_filter/file.gz.sig differ
diff --git a/tests/file_filter/file.lzop b/tests/file_filter/file.lzop
new file mode 100644
index 000000000..5f5a97171
Binary files /dev/null and b/tests/file_filter/file.lzop differ
diff --git a/tests/file_filter/file.lzop.sig b/tests/file_filter/file.lzop.sig
new file mode 100644
index 000000000..7c68dcf93
Binary files /dev/null and b/tests/file_filter/file.lzop.sig differ
diff --git a/tests/file_filter/file.xz b/tests/file_filter/file.xz
new file mode 100644
index 000000000..151a98029
Binary files /dev/null and b/tests/file_filter/file.xz differ
diff --git a/tests/file_filter/file.xz.sig b/tests/file_filter/file.xz.sig
new file mode 100644
index 000000000..57569242e
Binary files /dev/null and b/tests/file_filter/file.xz.sig differ
diff --git a/tests/file_filter/keys b/tests/file_filter/keys
new file mode 100644
index 000000000..1afa71382
Binary files /dev/null and b/tests/file_filter/keys differ
diff --git a/tests/file_filter/keys.pub b/tests/file_filter/keys.pub
new file mode 100644
index 000000000..61d4e7a7b
Binary files /dev/null and b/tests/file_filter/keys.pub differ
diff --git a/tests/file_filter/test.cfg b/tests/file_filter/test.cfg
new file mode 100644
index 000000000..4308aaca5
--- /dev/null
+++ b/tests/file_filter/test.cfg
@@ -0,0 +1,6 @@
+trust /keys.pub
+set check_signatures=enforce
+cat /file.gz
+cat /file.xz
+cat /file.lzop
+set check_signatures=
diff --git a/tests/file_filter_test.in b/tests/file_filter_test.in
new file mode 100644
index 000000000..8909e4021
--- /dev/null
+++ b/tests/file_filter_test.in
@@ -0,0 +1,76 @@
+#! /bin/sh
+# 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 <http://www.gnu.org/licenses/>.
+
+set -e
+grubshell=@builddir@/grub-shell
+
+. "@builddir@/grub-core/modinfo.sh"
+
+filters="gzio xzio lzopio verify"
+modules="cat mpi"
+
+for mod in $(cut -d ' ' -f 2 "@builddir@/grub-core/crypto.lst"  | sort -u); do
+    modules="$modules $mod"
+done
+
+for file in file.gz file.xz file.lzop file.gz.sig file.xz.sig file.lzop.sig keys.pub; do
+    files="$files /$file=@srcdir@/tests/file_filter/$file"
+done
+
+# GRUB cat command adds extra newline after file
+result="Hello, user!
+
+Hello, user!
+
+Hello, user!"
+
+out="$("${grubshell}" --modules="$modules $filters" --files="$files" "@srcdir@/tests/file_filter/test.cfg")"
+if [ "$out" != "$result" ]; then
+   echo LOCAL FAIL
+   echo "$out"
+   exit 1
+fi
+
+# Taken from netboot_test
+case "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" in
+    # PLATFORM: emu is different
+    *-emu)
+	exit 0;;
+    # PLATFORM: Flash targets
+    i386-qemu | i386-coreboot | mips-qemu_mips | mipsel-qemu_mips)
+	exit 0;;
+    # FIXME: currently grub-shell uses only -kernel for loongson
+    mipsel-loongson)
+	exit 0;;
+    # FIXME: no rtl8139 support
+    i386-multiboot)
+	exit 0;;
+    # FIXME: We don't fully support netboot on ARC
+    *-arc)
+	exit 0;;
+    # FIXME: Many QEMU firmware have no netboot capability
+    *-efi | i386-ieee1275 | powerpc-ieee1275 | sparc64-ieee1275)
+	exit 0;;
+esac
+
+out="$("${grubshell}" --boot=net --modules="$modules $filters" --files="$files" "@srcdir@/tests/file_filter/test.cfg")"
+if [ "$out" != "$result" ]; then
+   echo NET FAIL
+   echo "$out"
+   exit 1
+fi
+
+exit 0
diff --git a/tests/grub_cmd_test.in b/tests/grub_cmd_test.in
new file mode 100644
index 000000000..6269891c9
--- /dev/null
+++ b/tests/grub_cmd_test.in
@@ -0,0 +1,67 @@
+#! /bin/bash
+
+# create a randome file
+empty="`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" || exit 1
+non_empty="`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" || exit 1
+cat >$non_empty <<EOF
+hello world!
+EOF
+
+. "@builddir@/grub-core/modinfo.sh"
+
+if [ x"${grub_modinfo_platform}" = xemu ]; then
+    grub_empty="(host)$empty"
+    grub_non_empty="(host)$non_empty"
+    grub_dir="(host)${TMPDIR:-/tmp}"
+else
+    grub_empty="/boot/empty"
+    grub_non_empty="/boot/non_empty"
+    grub_dir="/boot/grub"
+fi
+
+
+outfile="`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" || exit 1
+@builddir@/grub-shell --files=$grub_empty=$empty  --files=$grub_non_empty=$non_empty>$outfile <<EOF
+if ! test -f $grub_empty; then
+  echo FAIL1
+fi
+if ! test -e $grub_empty; then
+  echo FAIL2
+fi
+if test -d $grub_empty; then
+  echo FAIL3
+fi
+if ! test -d $grub_dir; then
+  echo FAIL4
+fi
+if test -s $grub_empty; then
+  echo FAIL5
+fi
+if ! test -s $grub_non_empty; then
+  echo FAIL6
+fi
+if test -f $grub_empty -a foo = bar; then
+  echo FAIL7
+fi
+if test -e $grub_empty -a foo = bar; then
+  echo FAIL8
+fi
+if test -s $grub_non_empty -a foo = bar; then
+  echo FAIL9
+fi
+if test -d $grub_dir -a foo = bar; then
+  echo FAIL10
+fi
+
+EOF
+
+rm -f "$empty" "$non_empty"
+
+if grep FAIL "$outfile" > /dev/null 2>&1; then
+    echo "GRUB test command file tests failed."
+    cat "$outfile"
+    exit 1
+else
+    rm -f "${outfile}"
+    exit 0
+fi
diff --git a/tests/ntfs_test.in b/tests/ntfs_test.in
index 6bf09e691..e25c6384a 100644
--- a/tests/ntfs_test.in
+++ b/tests/ntfs_test.in
@@ -15,5 +15,10 @@ if ! which mkfs.ntfs >/dev/null 2>&1; then
    exit 77
 fi
 
+if ! which setfattr >/dev/null 2>&1; then
+   echo "setfattr not installed; cannot test ntfs."
+   exit 77
+fi
+
 "@builddir@/grub-fs-tester" ntfs
-"@builddir@/grub-fs-tester" ntfscomp
\ No newline at end of file
+"@builddir@/grub-fs-tester" ntfscomp
diff --git a/tests/syslinux/ubuntu10.04/isolinux/adtxt.cfg b/tests/syslinux/ubuntu10.04/isolinux/adtxt.cfg
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/syslinux/ubuntu10.04/isolinux/dtmenu.cfg b/tests/syslinux/ubuntu10.04/isolinux/dtmenu.cfg
new file mode 100644
index 000000000..2e107fade
--- /dev/null
+++ b/tests/syslinux/ubuntu10.04/isolinux/dtmenu.cfg
@@ -0,0 +1,52 @@
+menu hshift 9
+menu width 58
+
+menu begin desktop
+    include stdmenu.cfg
+    menu hshift 13
+    menu width 49
+    menu label Alternative desktop environments
+    menu title Desktop environment menu
+    label mainmenu-kde
+        menu label ^Back..
+        text help
+        Higher level options install the GNOME desktop environment
+        endtext
+        menu exit
+    menu begin kde-desktop
+        include stdmenu.cfg
+        menu label ^KDE
+        menu title KDE desktop boot menu
+        text help
+   Select the 'K Desktop Environment' for the Desktop task
+        endtext
+        label mainmenu-kde
+            menu label ^Back..
+            menu exit
+        include kde/menu.cfg
+    menu end
+    menu begin lxde-desktop
+        include stdmenu.cfg
+        menu label ^LXDE
+        menu title LXDE desktop boot menu
+        text help
+       Select the 'Lightweight X11 Desktop Environment' for the Desktop task
+        endtext
+        label mainmenu-lxde
+            menu label ^Back..
+            menu exit
+        include lxde/menu.cfg
+    menu end
+    menu begin xfce-desktop
+        include stdmenu.cfg
+        menu label ^Xfce
+        menu title Xfce desktop boot menu
+        text help
+   Select the 'Xfce lightweight desktop environment' for the Desktop task
+        endtext
+        label mainmenu-xfce
+            menu label ^Back..
+            menu exit
+        include xfce/menu.cfg
+    menu end
+menu end
diff --git a/tests/syslinux/ubuntu10.04/isolinux/exithelp.cfg b/tests/syslinux/ubuntu10.04/isolinux/exithelp.cfg
new file mode 100644
index 000000000..3119e654a
--- /dev/null
+++ b/tests/syslinux/ubuntu10.04/isolinux/exithelp.cfg
@@ -0,0 +1,3 @@
+label menu
+	kernel vesamenu.c32
+	config isolinux.cfg
diff --git a/tests/syslinux/ubuntu10.04/isolinux/gfxboot.cfg b/tests/syslinux/ubuntu10.04/isolinux/gfxboot.cfg
new file mode 100644
index 000000000..b799cb5cb
--- /dev/null
+++ b/tests/syslinux/ubuntu10.04/isolinux/gfxboot.cfg
@@ -0,0 +1,12 @@
+foreground=0xFFFFFF
+background=0x958490
+screen-colour=0x270A1E
+hidden-timeout=2
+label normal=Normal
+append normal=
+label driverupdates=Use driver update disc
+append driverupdates=debian-installer/driver-update=true
+applies driverupdates=live live-install
+label oem=OEM install (for manufacturers)
+append oem=oem-config/enable=true
+applies oem=live live-install install
diff --git a/tests/syslinux/ubuntu10.04/isolinux/isolinux.cfg b/tests/syslinux/ubuntu10.04/isolinux/isolinux.cfg
new file mode 100644
index 000000000..fd9c333b2
--- /dev/null
+++ b/tests/syslinux/ubuntu10.04/isolinux/isolinux.cfg
@@ -0,0 +1,6 @@
+# D-I config version 2.0
+include menu.cfg
+default vesamenu.c32
+prompt 0
+timeout 50
+ui gfxboot bootlogo
diff --git a/tests/syslinux/ubuntu10.04/isolinux/menu.cfg b/tests/syslinux/ubuntu10.04/isolinux/menu.cfg
new file mode 100644
index 000000000..9f5607dea
--- /dev/null
+++ b/tests/syslinux/ubuntu10.04/isolinux/menu.cfg
@@ -0,0 +1,23 @@
+menu hshift 13
+menu width 49
+menu margin 8
+
+menu title Installer boot menu
+include stdmenu.cfg
+include txt.cfg
+include gtk.cfg
+menu begin advanced
+	menu title Advanced options
+	include stdmenu.cfg
+	label mainmenu
+		menu label ^Back..
+		menu exit
+	include adtxt.cfg
+	include adgtk.cfg
+menu end
+label help
+	menu label ^Help
+	text help
+   Display help screens; type 'menu' at boot prompt to return to this menu
+	endtext
+	config prompt.cfg
diff --git a/tests/syslinux/ubuntu10.04/isolinux/po4a.cfg b/tests/syslinux/ubuntu10.04/isolinux/po4a.cfg
new file mode 100644
index 000000000..75f67881c
--- /dev/null
+++ b/tests/syslinux/ubuntu10.04/isolinux/po4a.cfg
@@ -0,0 +1,3 @@
+[po4a_langs] ar bn ca cs da de es eu fi fr gl hu id it ja ka ko ku lv nb nl pl pt pt_BR ru sk sv ta tr vi zh_CN zh_TW
+[po4a_paths] po/help.pot $lang:po/$lang.po
+[type:docbook] help.xml
diff --git a/tests/syslinux/ubuntu10.04/isolinux/prompt.cfg b/tests/syslinux/ubuntu10.04/isolinux/prompt.cfg
new file mode 100644
index 000000000..f9984aedc
--- /dev/null
+++ b/tests/syslinux/ubuntu10.04/isolinux/prompt.cfg
@@ -0,0 +1,16 @@
+prompt 1
+display f1.txt
+timeout 50
+include menu.cfg
+include exithelp.cfg
+
+f1 f1.txt
+f2 f2.txt
+f3 f3.txt
+f4 f4.txt
+f5 f5.txt
+f6 f6.txt
+f7 f7.txt
+f8 f8.txt
+f9 f9.txt
+f0 f10.txt
diff --git a/tests/syslinux/ubuntu10.04/isolinux/rqtxt.cfg b/tests/syslinux/ubuntu10.04/isolinux/rqtxt.cfg
new file mode 100644
index 000000000..bdf6231ae
--- /dev/null
+++ b/tests/syslinux/ubuntu10.04/isolinux/rqtxt.cfg
@@ -0,0 +1,4 @@
+label rescue
+	menu label ^Rescue mode
+	kernel /install/vmlinuz
+	append vga=788 initrd=/install/initrd.gz rescue/enable=true -- quiet 
diff --git a/tests/syslinux/ubuntu10.04/isolinux/stdmenu.cfg b/tests/syslinux/ubuntu10.04/isolinux/stdmenu.cfg
new file mode 100644
index 000000000..671b16f78
--- /dev/null
+++ b/tests/syslinux/ubuntu10.04/isolinux/stdmenu.cfg
@@ -0,0 +1,15 @@
+menu background splash.png
+menu color title	* #FFFFFFFF *
+menu color border	* #00000000 #00000000 none
+menu color sel		* #ffffffff #76a1d0ff *
+menu color hotsel	1;7;37;40 #ffffffff #76a1d0ff *
+menu color tabmsg	* #ffffffff #00000000 *
+menu color help		37;40 #ffdddd00 #00000000 none
+menu vshift 12
+menu rows 10
+menu helpmsgrow 15
+# The command line must be at least one line from the bottom.
+menu cmdlinerow 16
+menu timeoutrow 16
+menu tabmsgrow 18
+menu tabmsg Press ENTER to boot or TAB to edit a menu entry
diff --git a/tests/syslinux/ubuntu10.04/isolinux/txt.cfg b/tests/syslinux/ubuntu10.04/isolinux/txt.cfg
new file mode 100644
index 000000000..860daad80
--- /dev/null
+++ b/tests/syslinux/ubuntu10.04/isolinux/txt.cfg
@@ -0,0 +1,19 @@
+default live
+label live
+  menu label ^Try Ubuntu without installing
+  kernel /casper/vmlinuz
+  append  file=/cdrom/preseed/ubuntu.seed boot=casper initrd=/casper/initrd.lz quiet splash --
+label live-install
+  menu label ^Install Ubuntu
+  kernel /casper/vmlinuz
+  append  file=/cdrom/preseed/ubuntu.seed boot=casper only-ubiquity initrd=/casper/initrd.lz quiet splash --
+label check
+  menu label ^Check disc for defects
+  kernel /casper/vmlinuz
+  append  boot=casper integrity-check initrd=/casper/initrd.lz quiet splash --
+label memtest
+  menu label Test ^memory
+  kernel /install/mt86plus
+label hd
+  menu label ^Boot from first hard disk
+  localboot 0x80
diff --git a/tests/syslinux/ubuntu10.04_grub.cfg.in b/tests/syslinux/ubuntu10.04_grub.cfg.in
new file mode 100644
index 000000000..846e4acf0
--- /dev/null
+++ b/tests/syslinux/ubuntu10.04_grub.cfg.in
@@ -0,0 +1,236 @@
+  background_image '@abs_top_srcdir@/tests/syslinux/ubuntu10.04/isolinux'/'splash.png'
+# D-I config version 2.0
+  # UNSUPPORTED command 'menu hshift 13'
+  # UNSUPPORTED command 'menu width 49'
+  # UNSUPPORTED command 'menu margin 8'
+
+  # UNSUPPORTED command 'menu title Installer boot menu'
+  # UNSUPPORTED command 'menu color title	* #FFFFFFFF *'
+  # UNSUPPORTED command 'menu color border	* #00000000 #00000000 none'
+  # UNSUPPORTED command 'menu color sel		* #ffffffff #76a1d0ff *'
+  # UNSUPPORTED command 'menu color hotsel	1;7;37;40 #ffffffff #76a1d0ff *'
+  # UNSUPPORTED command 'menu color tabmsg	* #ffffffff #00000000 *'
+  # UNSUPPORTED command 'menu color help		37;40 #ffdddd00 #00000000 none'
+  # UNSUPPORTED command 'menu vshift 12'
+  # UNSUPPORTED command 'menu rows 10'
+  # UNSUPPORTED command 'menu helpmsgrow 15'
+# The command line must be at least one line from the bottom.
+  # UNSUPPORTED command 'menu cmdlinerow 16'
+  # UNSUPPORTED command 'menu timeoutrow 16'
+  # UNSUPPORTED command 'menu tabmsgrow 18'
+  # UNSUPPORTED command 'menu tabmsg Press ENTER to boot or TAB to edit a menu entry'
+set timeout=5
+ default='vesamenu.c32'
+menuentry 'Try Ubuntu without installing' --hotkey 't' --id 'live' {
+ if test x$grub_platform = xpc; then linux_suffix=16; else linux_suffix= ; fi
+  linux$linux_suffix '/'/'/casper/vmlinuz' file=/cdrom/preseed/ubuntu.seed boot=casper initrd=/casper/initrd.lz quiet splash --
+  initrd$linux_suffix '/'/'/casper/initrd.lz' 
+}
+menuentry 'Install Ubuntu' --hotkey 'i' --id 'live-install' {
+ if test x$grub_platform = xpc; then linux_suffix=16; else linux_suffix= ; fi
+  linux$linux_suffix '/'/'/casper/vmlinuz' file=/cdrom/preseed/ubuntu.seed boot=casper only-ubiquity initrd=/casper/initrd.lz quiet splash --
+  initrd$linux_suffix '/'/'/casper/initrd.lz' 
+}
+menuentry 'Check disc for defects' --hotkey 'c' --id 'check' {
+ if test x$grub_platform = xpc; then linux_suffix=16; else linux_suffix= ; fi
+  linux$linux_suffix '/'/'/casper/vmlinuz' boot=casper integrity-check initrd=/casper/initrd.lz quiet splash --
+  initrd$linux_suffix '/'/'/casper/initrd.lz' 
+}
+menuentry 'Test memory' --hotkey 'm' --id 'memtest' {
+ if test x$grub_platform = xpc; then linux_suffix=16; else linux_suffix= ; fi
+  linux$linux_suffix '/'/'/install/mt86plus' 
+}
+menuentry 'Boot from first hard disk' --hotkey 'b' --id 'hd' {
+# File (host)/@abs_top_srcdir@/tests/syslinux/ubuntu10.04/isolinux/gtk.cfg not found
+  # UNSUPPORTED command 'menu begin advanced'
+  # UNSUPPORTED command 'menu title Advanced options'
+  # UNSUPPORTED command 'menu color title	* #FFFFFFFF *'
+  # UNSUPPORTED command 'menu color border	* #00000000 #00000000 none'
+  # UNSUPPORTED command 'menu color sel		* #ffffffff #76a1d0ff *'
+  # UNSUPPORTED command 'menu color hotsel	1;7;37;40 #ffffffff #76a1d0ff *'
+  # UNSUPPORTED command 'menu color tabmsg	* #ffffffff #00000000 *'
+  # UNSUPPORTED command 'menu color help		37;40 #ffdddd00 #00000000 none'
+  # UNSUPPORTED command 'menu vshift 12'
+  # UNSUPPORTED command 'menu rows 10'
+  # UNSUPPORTED command 'menu helpmsgrow 15'
+# The command line must be at least one line from the bottom.
+  # UNSUPPORTED command 'menu cmdlinerow 16'
+  # UNSUPPORTED command 'menu timeoutrow 16'
+  # UNSUPPORTED command 'menu tabmsgrow 18'
+  # UNSUPPORTED command 'menu tabmsg Press ENTER to boot or TAB to edit a menu entry'
+  root=hd0;
+  chainloader +1;
+}
+menuentry 'Back..' --hotkey 'b' --id 'mainmenu' {
+  # UNSUPPORTED command 'menu exit'
+# File (host)/@abs_top_srcdir@/tests/syslinux/ubuntu10.04/isolinux/adgtk.cfg not found
+  # UNSUPPORTED command 'menu end'
+  # UNSUPPORTED entry type 0
+true;
+}
+menuentry 'Help' --hotkey 'h' --id 'help' {
+  # UNSUPPORTED command 'ui gfxboot bootlogo'
+#'@abs_top_srcdir@/tests/syslinux/ubuntu10.04/isolinux'/'prompt.cfg' (host)@abs_top_srcdir@/tests/syslinux/ubuntu10.04/isolinux/prompt.cfg:
+  background_image '@abs_top_srcdir@/tests/syslinux/ubuntu10.04/isolinux/'/'splash.png'
+  # UNSUPPORTED command 'display f1.txt'
+  # UNSUPPORTED command 'menu hshift 13'
+  # UNSUPPORTED command 'menu width 49'
+  # UNSUPPORTED command 'menu margin 8'
+
+  # UNSUPPORTED command 'menu title Installer boot menu'
+  # UNSUPPORTED command 'menu color title	* #FFFFFFFF *'
+  # UNSUPPORTED command 'menu color border	* #00000000 #00000000 none'
+  # UNSUPPORTED command 'menu color sel		* #ffffffff #76a1d0ff *'
+  # UNSUPPORTED command 'menu color hotsel	1;7;37;40 #ffffffff #76a1d0ff *'
+  # UNSUPPORTED command 'menu color tabmsg	* #ffffffff #00000000 *'
+  # UNSUPPORTED command 'menu color help		37;40 #ffdddd00 #00000000 none'
+  # UNSUPPORTED command 'menu vshift 12'
+  # UNSUPPORTED command 'menu rows 10'
+  # UNSUPPORTED command 'menu helpmsgrow 15'
+# The command line must be at least one line from the bottom.
+  # UNSUPPORTED command 'menu cmdlinerow 16'
+  # UNSUPPORTED command 'menu timeoutrow 16'
+  # UNSUPPORTED command 'menu tabmsgrow 18'
+  # UNSUPPORTED command 'menu tabmsg Press ENTER to boot or TAB to edit a menu entry'
+set timeout=5
+ default='live'
+menuentry 'Try Ubuntu without installing' --hotkey 't' --id 'live' {
+ if test x$grub_platform = xpc; then linux_suffix=16; else linux_suffix= ; fi
+  linux$linux_suffix '/'/'/casper/vmlinuz' file=/cdrom/preseed/ubuntu.seed boot=casper initrd=/casper/initrd.lz quiet splash --
+  initrd$linux_suffix '/'/'/casper/initrd.lz' 
+}
+menuentry 'Install Ubuntu' --hotkey 'i' --id 'live-install' {
+ if test x$grub_platform = xpc; then linux_suffix=16; else linux_suffix= ; fi
+  linux$linux_suffix '/'/'/casper/vmlinuz' file=/cdrom/preseed/ubuntu.seed boot=casper only-ubiquity initrd=/casper/initrd.lz quiet splash --
+  initrd$linux_suffix '/'/'/casper/initrd.lz' 
+}
+menuentry 'Check disc for defects' --hotkey 'c' --id 'check' {
+ if test x$grub_platform = xpc; then linux_suffix=16; else linux_suffix= ; fi
+  linux$linux_suffix '/'/'/casper/vmlinuz' boot=casper integrity-check initrd=/casper/initrd.lz quiet splash --
+  initrd$linux_suffix '/'/'/casper/initrd.lz' 
+}
+menuentry 'Test memory' --hotkey 'm' --id 'memtest' {
+ if test x$grub_platform = xpc; then linux_suffix=16; else linux_suffix= ; fi
+  linux$linux_suffix '/'/'/install/mt86plus' 
+}
+menuentry 'Boot from first hard disk' --hotkey 'b' --id 'hd' {
+# File (host)/@abs_top_srcdir@/tests/syslinux/ubuntu10.04/isolinux//gtk.cfg not found
+  # UNSUPPORTED command 'menu begin advanced'
+  # UNSUPPORTED command 'menu title Advanced options'
+  # UNSUPPORTED command 'menu color title	* #FFFFFFFF *'
+  # UNSUPPORTED command 'menu color border	* #00000000 #00000000 none'
+  # UNSUPPORTED command 'menu color sel		* #ffffffff #76a1d0ff *'
+  # UNSUPPORTED command 'menu color hotsel	1;7;37;40 #ffffffff #76a1d0ff *'
+  # UNSUPPORTED command 'menu color tabmsg	* #ffffffff #00000000 *'
+  # UNSUPPORTED command 'menu color help		37;40 #ffdddd00 #00000000 none'
+  # UNSUPPORTED command 'menu vshift 12'
+  # UNSUPPORTED command 'menu rows 10'
+  # UNSUPPORTED command 'menu helpmsgrow 15'
+# The command line must be at least one line from the bottom.
+  # UNSUPPORTED command 'menu cmdlinerow 16'
+  # UNSUPPORTED command 'menu timeoutrow 16'
+  # UNSUPPORTED command 'menu tabmsgrow 18'
+  # UNSUPPORTED command 'menu tabmsg Press ENTER to boot or TAB to edit a menu entry'
+  root=hd0;
+  chainloader +1;
+}
+menuentry 'Back..' --hotkey 'b' --id 'mainmenu' {
+  # UNSUPPORTED command 'menu exit'
+# File (host)/@abs_top_srcdir@/tests/syslinux/ubuntu10.04/isolinux//adgtk.cfg not found
+  # UNSUPPORTED command 'menu end'
+  # UNSUPPORTED entry type 0
+true;
+}
+menuentry 'Help' --hotkey 'h' --id 'help' {
+#'@abs_top_srcdir@/tests/syslinux/ubuntu10.04/isolinux/'/'prompt.cfg' (host)@abs_top_srcdir@/tests/syslinux/ubuntu10.04/isolinux/prompt.cfg:
+  syslinux_configfile -r '/'/'/' -c '@abs_top_srcdir@/tests/syslinux/ubuntu10.04/isolinux/'/'' '@abs_top_srcdir@/tests/syslinux/ubuntu10.04/isolinux/'/'prompt.cfg'
+}
+menuentry 'menu' --id 'menu' {
+  # UNSUPPORTED command 'f1 f1.txt'
+  # UNSUPPORTED command 'f2 f2.txt'
+  # UNSUPPORTED command 'f3 f3.txt'
+  # UNSUPPORTED command 'f4 f4.txt'
+  # UNSUPPORTED command 'f5 f5.txt'
+  # UNSUPPORTED command 'f6 f6.txt'
+  # UNSUPPORTED command 'f7 f7.txt'
+  # UNSUPPORTED command 'f8 f8.txt'
+  # UNSUPPORTED command 'f9 f9.txt'
+  # UNSUPPORTED command 'f0 f10.txt'
+#'@abs_top_srcdir@/tests/syslinux/ubuntu10.04/isolinux/'/'isolinux.cfg' (host)@abs_top_srcdir@/tests/syslinux/ubuntu10.04/isolinux/isolinux.cfg:
+  background_image '@abs_top_srcdir@/tests/syslinux/ubuntu10.04/isolinux//'/'splash.png'
+# D-I config version 2.0
+  # UNSUPPORTED command 'menu hshift 13'
+  # UNSUPPORTED command 'menu width 49'
+  # UNSUPPORTED command 'menu margin 8'
+
+  # UNSUPPORTED command 'menu title Installer boot menu'
+  # UNSUPPORTED command 'menu color title	* #FFFFFFFF *'
+  # UNSUPPORTED command 'menu color border	* #00000000 #00000000 none'
+  # UNSUPPORTED command 'menu color sel		* #ffffffff #76a1d0ff *'
+  # UNSUPPORTED command 'menu color hotsel	1;7;37;40 #ffffffff #76a1d0ff *'
+  # UNSUPPORTED command 'menu color tabmsg	* #ffffffff #00000000 *'
+  # UNSUPPORTED command 'menu color help		37;40 #ffdddd00 #00000000 none'
+  # UNSUPPORTED command 'menu vshift 12'
+  # UNSUPPORTED command 'menu rows 10'
+  # UNSUPPORTED command 'menu helpmsgrow 15'
+# The command line must be at least one line from the bottom.
+  # UNSUPPORTED command 'menu cmdlinerow 16'
+  # UNSUPPORTED command 'menu timeoutrow 16'
+  # UNSUPPORTED command 'menu tabmsgrow 18'
+  # UNSUPPORTED command 'menu tabmsg Press ENTER to boot or TAB to edit a menu entry'
+set timeout=5
+ default='vesamenu.c32'
+menuentry 'Try Ubuntu without installing' --hotkey 't' --id 'live' {
+ if test x$grub_platform = xpc; then linux_suffix=16; else linux_suffix= ; fi
+  linux$linux_suffix '/'/'/casper/vmlinuz' file=/cdrom/preseed/ubuntu.seed boot=casper initrd=/casper/initrd.lz quiet splash --
+  initrd$linux_suffix '/'/'/casper/initrd.lz' 
+}
+menuentry 'Install Ubuntu' --hotkey 'i' --id 'live-install' {
+ if test x$grub_platform = xpc; then linux_suffix=16; else linux_suffix= ; fi
+  linux$linux_suffix '/'/'/casper/vmlinuz' file=/cdrom/preseed/ubuntu.seed boot=casper only-ubiquity initrd=/casper/initrd.lz quiet splash --
+  initrd$linux_suffix '/'/'/casper/initrd.lz' 
+}
+menuentry 'Check disc for defects' --hotkey 'c' --id 'check' {
+ if test x$grub_platform = xpc; then linux_suffix=16; else linux_suffix= ; fi
+  linux$linux_suffix '/'/'/casper/vmlinuz' boot=casper integrity-check initrd=/casper/initrd.lz quiet splash --
+  initrd$linux_suffix '/'/'/casper/initrd.lz' 
+}
+menuentry 'Test memory' --hotkey 'm' --id 'memtest' {
+ if test x$grub_platform = xpc; then linux_suffix=16; else linux_suffix= ; fi
+  linux$linux_suffix '/'/'/install/mt86plus' 
+}
+menuentry 'Boot from first hard disk' --hotkey 'b' --id 'hd' {
+# File (host)/@abs_top_srcdir@/tests/syslinux/ubuntu10.04/isolinux///gtk.cfg not found
+  # UNSUPPORTED command 'menu begin advanced'
+  # UNSUPPORTED command 'menu title Advanced options'
+  # UNSUPPORTED command 'menu color title	* #FFFFFFFF *'
+  # UNSUPPORTED command 'menu color border	* #00000000 #00000000 none'
+  # UNSUPPORTED command 'menu color sel		* #ffffffff #76a1d0ff *'
+  # UNSUPPORTED command 'menu color hotsel	1;7;37;40 #ffffffff #76a1d0ff *'
+  # UNSUPPORTED command 'menu color tabmsg	* #ffffffff #00000000 *'
+  # UNSUPPORTED command 'menu color help		37;40 #ffdddd00 #00000000 none'
+  # UNSUPPORTED command 'menu vshift 12'
+  # UNSUPPORTED command 'menu rows 10'
+  # UNSUPPORTED command 'menu helpmsgrow 15'
+# The command line must be at least one line from the bottom.
+  # UNSUPPORTED command 'menu cmdlinerow 16'
+  # UNSUPPORTED command 'menu timeoutrow 16'
+  # UNSUPPORTED command 'menu tabmsgrow 18'
+  # UNSUPPORTED command 'menu tabmsg Press ENTER to boot or TAB to edit a menu entry'
+  root=hd0;
+  chainloader +1;
+}
+menuentry 'Back..' --hotkey 'b' --id 'mainmenu' {
+  # UNSUPPORTED command 'menu exit'
+# File (host)/@abs_top_srcdir@/tests/syslinux/ubuntu10.04/isolinux///adgtk.cfg not found
+  # UNSUPPORTED command 'menu end'
+  # UNSUPPORTED entry type 0
+true;
+}
+menuentry 'Help' --hotkey 'h' --id 'help' {
+  # UNSUPPORTED command 'ui gfxboot bootlogo'
+#'@abs_top_srcdir@/tests/syslinux/ubuntu10.04/isolinux//'/'prompt.cfg' (host)@abs_top_srcdir@/tests/syslinux/ubuntu10.04/isolinux/prompt.cfg:
+  syslinux_configfile -r '/'/'/' -c '@abs_top_srcdir@/tests/syslinux/ubuntu10.04/isolinux//'/'' '@abs_top_srcdir@/tests/syslinux/ubuntu10.04/isolinux//'/'prompt.cfg'
+}
+}
+}
diff --git a/tests/syslinux_test.in b/tests/syslinux_test.in
new file mode 100644
index 000000000..fc4edd8ef
--- /dev/null
+++ b/tests/syslinux_test.in
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+set -e
+
+outfile="`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" || exit 1
+
+"@builddir@/grub-syslinux2cfg" -r "@abs_top_srcdir@/tests/syslinux/ubuntu10.04" "@abs_top_srcdir@/tests/syslinux/ubuntu10.04/isolinux/isolinux.cfg" -o "$outfile"
+
+echo "$outfile"
+
+if ! diff -u "$outfile" "@builddir@/tests/syslinux/ubuntu10.04_grub.cfg"; then
+  echo "Mismatch in ubuntu10.04"
+  exit 1;
+fi
+
+exit 0
diff --git a/tests/test_sha512sum.in b/tests/test_sha512sum.in
index 524c1d1c0..d5ef7f9ea 100644
--- a/tests/test_sha512sum.in
+++ b/tests/test_sha512sum.in
@@ -1,7 +1,7 @@
 #! /bin/bash
 
 # create a randome file
-file=`mktemp`
+file="`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" || exit 1
 cat >$file <<EOF
 hello world!
 EOF
@@ -15,12 +15,12 @@ else
 fi
 
 
-outfile1=`mktemp`
+outfile1="`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" || exit 1
 @builddir@/grub-shell --files=/boot/grub/file=$file >$outfile1 <<EOF
 sha512sum $grub_file
 EOF
 
-outfile2=`mktemp`
+outfile2="`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" || exit 1
 sha512sum $file >$outfile2
 
 SHA1=`cat $outfile1 | tr -d '\n' | cut -f1 -d\ `
diff --git a/tests/util/grub-fs-tester.in b/tests/util/grub-fs-tester.in
index 0533d38bb..9c1c2f5e2 100644
--- a/tests/util/grub-fs-tester.in
+++ b/tests/util/grub-fs-tester.in
@@ -102,7 +102,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 		# OS LIMITATION: Linux oopses with >=32768K
 	    MAXBLKSIZE=$((16384*1024))
 	    ;;
-	x"lvm_raid4" | x"lvm_raid5" | x"lvm_raid6")
+	x"lvm_raid1"* | x"lvm_raid4" | x"lvm_raid5" | x"lvm_raid6")
 		# OS LIMITATION: Linux crashes with less than 16384
 	    MINBLKSIZE=16384
 		# Could go further but what's the point?
@@ -166,7 +166,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 	    x"zfs_raidz" | x"zfs_stripe" | x"zfs_mirror" | xbtrfs_raid0 \
 		| xbtrfs_raid1 | x"mdraid"*"_raid4" | x"mdraid"*"_raid5" \
 		| x"mdraid"*"_linear" \
-		| x"mdraid"*"_raid10" | xlvm_mirror1 | xlvm_mirrorall)
+		| x"mdraid"*"_raid10" | xlvm_raid1* | xlvm_mirror1 | xlvm_mirrorall)
 		MINDEVICES=2
 		MAXDEVICES=7
 		;;
@@ -199,7 +199,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 
 	    case x$fs in
   	    # RAID 1 has to work with even one device of the set.
-		xzfs_mirror | x"mdraid"*"_raid1" | xlvm_mirrorall)
+		xzfs_mirror | x"mdraid"*"_raid1" | xlvm_mirrorall | xlvm_raid1all)
 		    NEED_IMAGES_N=1;;
             # Degrade raidz by removing 3 devices
 		xzfs_raidz3)
@@ -210,7 +210,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 	    # Degrade raidz and btrfs RAID1 by removing one device
  		xbtrfs_raid1 | xbtrfs_raid10 | xzfs_raidz | x"mdraid"*"_raid4" \
 		    | x"mdraid"*"_raid5" | x"mdraid"*"_raid10" | xlvm_mirror1 \
-		    | x"lvm_raid4" | x"lvm_raid5")
+		    | x"lvm_raid1" | x"lvm_raid4" | x"lvm_raid5")
 		    NEED_IMAGES_N=$((NDEVICES-1));;
 		*)
 		    NEED_IMAGES_N=$NDEVICES;;
@@ -283,7 +283,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 		    #FSLABEL="g;/_é莭莽😁кит u"
 		    ;;
 	    # FS LIMITATION: reiserfs, extN and jfs label is at most 16 UTF-8 characters
-		x"reiserfs_old" | x"reiserfs" | x"ext2" | xext2_old | x"ext3" | x"ext4" | x"lvm"* | x"mdraid"* | x"jfs" | x"jfs_caseins")
+		x"reiserfs_old" | x"reiserfs" | x"ext"* | x"lvm"* | x"mdraid"* | x"jfs" | x"jfs_caseins")
 		    FSLABEL="g;/éт 莭😁";;
             # FS LIMITATION: No underscore, space, semicolon, slash or international characters in UFS* in label. Limited to 32 UTF-8 characters
 		x"ufs1" | x"ufs1_sun" | x"ufs2")
@@ -730,10 +730,15 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 			lvcreate -l "$((NDEVICES*7*LVMBLKMUL))" -n testvol grub_test
 		    elif [ x$fs = xlvm_stripe ] ; then
 			lvcreate -l "$((NDEVICES*7*LVMBLKMUL))" -i "$NDEVICES" -n testvol grub_test
-		    elif [ x$fs = xlvm_mirror1 ] ; then
-			lvcreate -m 1 -l "$((NDEVICES*2*LVMBLKMUL))" -n testvol grub_test
+		    elif [ x$fs = xlvm_mirror1 ] || [ x$fs = xlvm_raid1 ] ; then
+			lvcreate -m 1 -l "$((NDEVICES*2*LVMBLKMUL))" --type "${fs/lvm_/}" -n testvol grub_test
 		    elif [ x$fs = xlvm_mirrorall ] ; then
-			lvcreate -m "$((NDEVICES-1))" -l "$((6*LVMBLKMUL))" -n testvol grub_test
+			lvcreate -m "$((NDEVICES-1))" -l "$((6*LVMBLKMUL))" --type mirror -n testvol grub_test
+		    elif [ x$fs = xlvm_raid1all ] ; then
+			# Until version 2.02.103 LVM counts metadata segments
+			# twice when checking available space. Reduce segment
+			# count to work around it.
+			lvcreate -m "$((NDEVICES-1))" -l "$((6*LVMBLKMUL - 1))" --type raid1 -n testvol grub_test
 		    elif [ x$fs = xlvm_raid4 ] || [ x$fs = xlvm_raid5 ]; then
 			lvcreate -l "$(((NDEVICES-1) * 5*LVMBLKMUL))" -i "$((NDEVICES-1))" --type "${fs/lvm_/}" -n testvol grub_test
 		    elif [ x$fs = xlvm_raid6 ]; then
@@ -748,6 +753,10 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 		    MKE2FS_DEVICE_SECTSIZE=$SECSIZE "mkfs.ext2" -r 0 -b $BLKSIZE -L "$FSLABEL" -q "${LODEVICES[0]}"
 		    MOUNTFS=ext2
 		    ;;
+		xext4_metabg)
+		    MKE2FS_DEVICE_SECTSIZE=$SECSIZE "mkfs.ext4" -O meta_bg,^resize_inode -b $BLKSIZE -L "$FSLABEL" -q "${LODEVICES[0]}"
+		    MOUNTFS=ext4
+		    ;;
 		xext*)
 		    MKE2FS_DEVICE_SECTSIZE=$SECSIZE "mkfs.$fs" -b $BLKSIZE -L "$FSLABEL" -q "${LODEVICES[0]}" ;;
 		xxfs)
@@ -991,6 +1000,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 			fi
 			sleep 1;
 		    done
+		    UMOUNT_TIME=$(date -u "+%Y-%m-%d %H:%M:%S")
 		    sleep 1
 		    vgchange -a n grub_test
 		    ;;
@@ -1002,6 +1012,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 			fi
 			sleep 1;
 		    done
+		    UMOUNT_TIME=$(date -u "+%Y-%m-%d %H:%M:%S")
 		    sleep 1
 		    mdadm --stop /dev/md/"${fs}_$NDEVICES"
 		    ;;
@@ -1212,10 +1223,15 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 	    case x$fs in
 		xiso9660 | xziso9660 | xrockridge | xjoliet | xrockridge_joliet | xiso9660_1999 | xrockridge_1999 | xjoliet_1999 | xrockridge_joliet_1999)
 		    FSTIME="$(date -d "$(echo ${FSUUID} | awk -F - '{ print $1"-"$2"-"$3" "$4":"$5":"$6 ;}')" '+%Y-%m-%d %H:%M:%S')";;
+		xlvm*|xmdraid*)
+		    # With some abstractions like mdraid flushing to disk
+		    # may be delayed for a long time.
+		    FSTIME="$UMOUNT_TIME";;
 		*)
 		    FSTIME="$(TZ=UTC ls --time-style="+%Y-%m-%d_%H:%M:%S" -l -d "${FSIMAGES[0]}"|awk '{print $6; }'|sed 's,_, ,g')";;
 	    esac
-		# With some abstractions like mdraid it may take up to 2 seconds for the data to reach the disks after it was flushed by FS in these tests.
+	    # With some abstractions like mdraid computing of UMOUNT_TIME
+	    # is not precise. Account for small difference here.
 	    FSTIMEM1="$(date -d "$FSTIME UTC -1 second" -u "+%Y-%m-%d %H:%M:%S")"
 	    FSTIMEM2="$(date -d "$FSTIME UTC -2 second" -u "+%Y-%m-%d %H:%M:%S")"
 
diff --git a/tests/util/grub-shell.in b/tests/util/grub-shell.in
index d9a5253e2..6d2b1327e 100644
--- a/tests/util/grub-shell.in
+++ b/tests/util/grub-shell.in
@@ -349,6 +349,7 @@ fi
 if [ x$boot != xnet ] && [ x$boot != xemu ]; then
     pkgdatadir="@builddir@" "@builddir@/grub-mkrescue" "--output=${isofile}" "--override-directory=${builddir}/grub-core" \
 	--rom-directory="${rom_directory}" \
+	--locale-directory="@srcdir@/po" \
 	--themes-directory="@srcdir@/themes" \
 	$mkimage_extra_arg ${mkrescue_args} \
 	"/boot/grub/grub.cfg=${cfgfile}" "/boot/grub/testcase.cfg=${source}" \
@@ -422,11 +423,28 @@ do_trim ()
     fi
 }
 
+copy_extra_files() {
+    _destdir="$1"
+    shift
+
+    # FIXME support '=' in file names
+    for _file in "$@"; do
+	_target="${_file%=*}"
+	_source="${_file#*=}"
+	[ -n "$_source" ] || _source="$_target"
+	_target="$_destdir/$_target"
+	_targetdir="$(dirname "$_target")"
+	[ -d "$_targetdir" ] || mkdir -p "$_targetdir"
+	cp "$_source" "$_target"
+    done
+}
+
 if [ x$boot = xnet ]; then
     netdir=`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1
     pkgdatadir="@builddir@" "@builddir@/grub-mknetdir" "--grub-mkimage=${builddir}/grub-mkimage" "--directory=${builddir}/grub-core" "--net-directory=$netdir" ${mkrescue_args} > /dev/null
     cp "${cfgfile}" "$netdir/boot/grub/grub.cfg"
     cp "${source}" "$netdir/boot/grub/testcase.cfg"
+    [ -z "$files" ] || copy_extra_files "$netdir" $files
     timeout -s KILL $timeout "${qemu}" ${qemuopts} ${serial_null} -serial file:/dev/stdout -boot n -net "user,tftp=$netdir,bootfile=/boot/grub/${grub_modinfo_target_cpu}-${grub_modinfo_platform}/core.$netbootext"  -net nic  | cat | tr -d "\r" | do_trim
 elif [ x$boot = xemu ]; then
     grubdir="$(mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX")"
diff --git a/util/getroot.c b/util/getroot.c
index 3958105d8..36f1730c0 100644
--- a/util/getroot.c
+++ b/util/getroot.c
@@ -107,6 +107,7 @@ grub_util_pull_device (const char *os_dev)
     default:
       if (grub_util_pull_device_os (os_dev, ab))
 	return;
+      /* Fallthrough.  */
     case GRUB_DEV_ABSTRACTION_NONE:
       free (grub_util_biosdisk_get_grub_dev (os_dev));
       return;
@@ -405,7 +406,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
 	       os_dev);
 	    grub_errno = GRUB_ERR_NONE;
 
-	    canon = canonicalize_file_name (os_dev);
+	    canon = grub_canonicalize_file_name (os_dev);
 	    drive = grub_hostdisk_os_dev_to_grub_drive (canon ? : os_dev, 1);
 	    if (canon)
 	      free (canon);
@@ -417,7 +418,10 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
 
     name = grub_util_get_ldm (disk, ctx.start);
     if (name)
-      return name;
+      {
+	grub_disk_close (disk);
+	return name;
+      }
 
     ctx.partname = NULL;
 
diff --git a/util/grub-file.c b/util/grub-file.c
index 9989dfe7b..50c18b683 100644
--- a/util/grub-file.c
+++ b/util/grub-file.c
@@ -77,7 +77,7 @@ main (int argc, char *argv[])
 	}
       if (had_file)
 	grub_util_error ("one argument expected");
-      argv2[i - 1] = canonicalize_file_name (argv[i]);
+      argv2[i - 1] = grub_canonicalize_file_name (argv[i]);
       if (!argv2[i - 1])
 	{
 	  grub_util_error (_("cannot open `%s': %s"), argv[i],
diff --git a/util/grub-fstest.c b/util/grub-fstest.c
index 31af2a7ad..a358ae471 100644
--- a/util/grub-fstest.c
+++ b/util/grub-fstest.c
@@ -570,12 +570,12 @@ argp_parser (int key, char *arg, struct argp_state *state)
 	    return 0;
 	  }
 	real_size = fread (buf, 1, 1024, f);
+	fclose (f);
 	if (real_size < 0)
 	  {
 	    printf (_("%s: error:"), program_name);
 	    printf (_("cannot read `%s': %s"), arg, strerror (errno));
 	    printf ("\n");
-	    fclose (f);
 	    return 0;
 	  }
 	grub_zfs_add_key (buf, real_size, 0);
@@ -651,7 +651,7 @@ argp_parser (int key, char *arg, struct argp_state *state)
     {
       if (args_count == 0)
 	images = xmalloc (num_disks * sizeof (images[0]));
-      images[args_count] = canonicalize_file_name (arg);
+      images[args_count] = grub_canonicalize_file_name (arg);
       args_count++;
       return 0;
     }
diff --git a/util/grub-install-common.c b/util/grub-install-common.c
index c8bedcb2e..37c1a98b9 100644
--- a/util/grub-install-common.c
+++ b/util/grub-install-common.c
@@ -238,7 +238,7 @@ grub_install_push_module (const char *val)
       if (modules.n_alloc < 16)
 	modules.n_alloc = 16;
       modules.entries = xrealloc (modules.entries,
-				  modules.n_alloc * sizeof (modules.entries));
+				  modules.n_alloc * sizeof (*modules.entries));
     }
   modules.entries[modules.n_entries++] = xstrdup (val);
   modules.entries[modules.n_entries] = NULL;
@@ -490,6 +490,7 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
 		  dir, prefix,
 		  outname, mkimage_target,
 		  compnames[compression], note ? "--note" : "", s);
+  free (s);
 
   tgt = grub_install_get_image_target (mkimage_target);
   if (!tgt)
@@ -902,7 +903,7 @@ grub_install_get_target (const char *src)
   char *fn;
   grub_util_fd_t f;
   char buf[2048];
-  size_t r;
+  ssize_t r;
   char *c, *pl, *p;
   size_t i;
   fn = grub_util_path_concat (2, src, "modinfo.sh");
@@ -911,6 +912,8 @@ grub_install_get_target (const char *src)
     grub_util_error (_("%s doesn't exist. Please specify --target or --directory"), 
 		     fn);
   r = grub_util_fd_read (f, buf, sizeof (buf) - 1);
+  if (r < 0)
+    grub_util_error (_("cannot read `%s': %s"), fn, strerror (errno));
   grub_util_fd_close (f);
   buf[r] = '\0';
   c = strstr (buf, "grub_modinfo_target_cpu=");
diff --git a/util/grub-install.c b/util/grub-install.c
index 7d61c32be..7b394c997 100644
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -615,8 +615,6 @@ device_map_check_duplicates (const char *dev_map)
   char **d;
   size_t i;
 
-  d = xmalloc (alloced * sizeof (d[0]));
-
   if (dev_map[0] == '\0')
     return;
 
@@ -624,6 +622,8 @@ device_map_check_duplicates (const char *dev_map)
   if (! fp)
     return;
 
+  d = xmalloc (alloced * sizeof (d[0]));
+
   while (fgets (buf, sizeof (buf), fp))
     {
       char *p = buf;
@@ -967,7 +967,7 @@ main (int argc, char *argv[])
   {
     char * t = grub_util_path_concat (2, bootdir, GRUB_DIR_NAME);
     grub_install_mkdir_p (t);
-    grubdir = canonicalize_file_name (t);
+    grubdir = grub_canonicalize_file_name (t);
     if (!grubdir)
       grub_util_error (_("failed to get canonical path of `%s'"), t);
     free (t);
@@ -1299,7 +1299,7 @@ main (int argc, char *argv[])
   {
     char *t = grub_util_path_concat (2, grubdir,
 				   platname);
-    platdir = canonicalize_file_name (t);
+    platdir = grub_canonicalize_file_name (t);
     if (!platdir)
       grub_util_error (_("failed to get canonical path of `%s'"),
 		       t);
@@ -1809,7 +1809,7 @@ main (int argc, char *argv[])
 	  grub_install_copy_file (imgfile, dst, 1);
 	  free (dst);
 	}
-
+      /* Fallthrough.  */
     case GRUB_INSTALL_PLATFORM_X86_64_EFI:
       if (efidir_is_mac)
 	{
diff --git a/util/grub-macbless.c b/util/grub-macbless.c
index 742353a42..e9b15a053 100644
--- a/util/grub-macbless.c
+++ b/util/grub-macbless.c
@@ -64,7 +64,7 @@ bless (const char *path, int x86)
   grub_err_t err;
   struct stat st;
 
-  grub_path = canonicalize_file_name (path);
+  grub_path = grub_canonicalize_file_name (path);
 
   if (stat (grub_path, &st) < 0)
     grub_util_error (N_("cannot stat `%s': %s"),
@@ -92,6 +92,8 @@ bless (const char *path, int x86)
   free (filebuf_via_grub);
   free (filebuf_via_sys);
   free (drive_name);
+  free (devices);
+  grub_device_close (dev);
 }
 
 static struct argp_option options[] = {
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
index d1fae4937..3183744bf 100644
--- a/util/grub-mkconfig.in
+++ b/util/grub-mkconfig.in
@@ -33,6 +33,9 @@ datadir="@datadir@"
 if [ "x$pkgdatadir" = x ]; then
     pkgdatadir="${datadir}/@PACKAGE@"
 fi
+# export it for scripts
+export pkgdatadir
+
 grub_cfg=""
 grub_mkconfig_dir="${sysconfdir}"/grub.d
 
diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
index 14fadbcbb..60b31cadd 100644
--- a/util/grub-mkconfig_lib.in
+++ b/util/grub-mkconfig_lib.in
@@ -145,7 +145,7 @@ prepare_grub_to_access_device ()
   done
 
   if [ x$GRUB_ENABLE_CRYPTODISK = xy ]; then
-      for uuid in "`"${grub_probe}" --device $@ --target=cryptodisk_uuid`"; do
+      for uuid in `"${grub_probe}" --device $@ --target=cryptodisk_uuid`; do
 	  echo "cryptomount -u $uuid"
       done
   fi
@@ -246,8 +246,8 @@ version_test_gt ()
   fi
   case "$version_test_gt_a:$version_test_gt_b" in
     *.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 ;;
+    *.old:*) version_test_gt_a="`echo "$version_test_gt_a" | sed -e 's/\.old$//'`" ; version_test_gt_cmp=gt ;;
+    *:*.old) version_test_gt_b="`echo "$version_test_gt_b" | sed -e 's/\.old$//'`" ; version_test_gt_cmp=ge ;;
   esac
   version_test_numeric "$version_test_gt_a" "$version_test_gt_cmp" "$version_test_gt_b"
   return "$?"
diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
index 0a1ac9e51..3c76d0708 100644
--- a/util/grub-mkimagexx.c
+++ b/util/grub-mkimagexx.c
@@ -1539,6 +1539,8 @@ SUFFIX (load_image) (const char *kernel_path, size_t *exec_size,
 	    symtab_section = s;
 	    break;
 	  }
+      if (! symtab_section)
+	grub_util_error ("%s", _("no symbol table"));
 
 #ifdef MKIMAGE_ELF32
       if (image_target->elf_target == EM_ARM)
@@ -1577,8 +1579,6 @@ SUFFIX (load_image) (const char *kernel_path, size_t *exec_size,
 	}
 #endif
 
-      if (! symtab_section)
-	grub_util_error ("%s", _("no symbol table"));
     }
   else
     {
diff --git a/util/grub-mkrescue.c b/util/grub-mkrescue.c
index e71983982..815fc9175 100644
--- a/util/grub-mkrescue.c
+++ b/util/grub-mkrescue.c
@@ -44,9 +44,6 @@ static char *label_color;
 static char *label_bgcolor;
 static char *product_name;
 static char *product_version;
-static int xorriso_tail_argc;
-static int xorriso_tail_arg_alloc;
-static char **xorriso_tail_argv;
 static char *output_image;
 static char *xorriso;
 static char *boot_grub;
@@ -215,16 +212,6 @@ argp_parser (int key, char *arg, struct argp_state *state)
       xorriso = xstrdup (arg);
       return 0;
 
-    case ARGP_KEY_ARG:
-      if (xorriso_tail_arg_alloc <= xorriso_tail_argc)
-	{
-	  xorriso_tail_arg_alloc = 2 * (4 + xorriso_tail_argc);
-	  xorriso_tail_argv = xrealloc (xorriso_tail_argv,
-				   sizeof (xorriso_tail_argv[0])
-				   * xorriso_tail_arg_alloc);
-	}
-      xorriso_tail_argv[xorriso_tail_argc++] = xstrdup (arg);
-      return 0;
     default:
       return ARGP_ERR_UNKNOWN;
     }
@@ -374,12 +361,70 @@ make_image_fwdisk (enum grub_install_plat plat,
   free (out);
 }
 
+static int
+option_is_end (const struct argp_option *opt)
+{
+  return !opt->key && !opt->name && !opt->doc && !opt->group;
+}
+
+
+static int
+args_to_eat (const char *arg)
+{
+  int j;
+
+  if (arg[0] != '-')
+    return 0;
+
+  if (arg[1] == '-')
+    {
+      for (j = 0; !option_is_end(&options[j]); j++)
+	{
+	  size_t len = strlen (options[j].name);
+	  if (strncmp (arg + 2, options[j].name, len) == 0)
+	    {
+	      if (arg[2 + len] == '=')
+		return 1;
+	      if (arg[2 + len] == '\0' && options[j].arg)
+		return 2;
+	      if (arg[2 + len] == '\0')
+		return 1;
+	    }
+	}
+      if (strcmp (arg, "--help") == 0)
+	return 1;
+      if (strcmp (arg, "--usage") == 0)
+	return 1;
+      if (strcmp (arg, "--version") == 0)
+	return 1;
+      return 0;
+    }
+  if (arg[2] && arg[3])
+    return 0;
+  for (j = 0; !option_is_end(&options[j]); j++)
+    {
+      if (options[j].key > 0 && options[j].key < 128 && arg[1] == options[j].key)
+	{
+	  if (options[j].arg)
+	    return 2;
+	  return 1;
+	}
+      if (arg[1] == '?')
+	return 1;
+    }
+  return 0;
+}
+
 int
 main (int argc, char *argv[])
 {
   char *romdir;
   char *sysarea_img = NULL;
   const char *pkgdatadir;
+  int argp_argc;
+  char **argp_argv;
+  int xorriso_tail_argc;
+  char **xorriso_tail_argv;
 
   grub_util_host_init (&argc, &argv);
   grub_util_disable_fd_syncs ();
@@ -391,7 +436,37 @@ main (int argc, char *argv[])
   xorriso = xstrdup ("xorriso");
   label_font = grub_util_path_concat (2, pkgdatadir, "unicode.pf2");
 
-  argp_parse (&argp, argc, argv, 0, 0, 0);
+  argp_argv = xmalloc (sizeof (argp_argv[0]) * argc);
+  xorriso_tail_argv = xmalloc (sizeof (argp_argv[0]) * argc);
+
+  xorriso_tail_argc = 0;
+  /* Program name */
+  argp_argv[0] = argv[0];
+  argp_argc = 1;
+
+  /* argp doesn't allow us to catch unknwon arguments,
+     so catch them before passing to argp
+   */
+  {
+    int i;
+    for (i = 1; i < argc; i++)
+      {
+	switch (args_to_eat (argv[i]))
+	  {
+	  case 2:
+	    argp_argv[argp_argc++] = argv[i++];
+	    /* Fallthrough  */
+	  case 1:
+	    argp_argv[argp_argc++] = argv[i];
+	    break;
+	  case 0:
+	    xorriso_tail_argv[xorriso_tail_argc++] = argv[i];
+	    break;
+	  }
+      }
+  }
+
+  argp_parse (&argp, argp_argc, argp_argv, 0, 0, 0);
 
   if (!output_image)
     grub_util_error ("%s", _("output file must be specified"));
@@ -653,6 +728,9 @@ main (int argc, char *argv[])
       char *efiimgfat;
       grub_install_mkdir_p (efidir_efi_boot);
 
+      grub_install_push_module ("part_gpt");
+      grub_install_push_module ("part_msdos");
+
       imgname = grub_util_path_concat (2, efidir_efi_boot, "bootia64.efi");
       make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_IA64_EFI, "ia64-efi", imgname);
       free (imgname);
@@ -713,6 +791,8 @@ main (int argc, char *argv[])
       free (efiimgfat);
       free (efidir_efi);
       free (efidir);
+      grub_install_pop_module ();
+      grub_install_pop_module ();
     }
 
   grub_install_push_module ("part_apple");
diff --git a/util/grub-mkstandalone.c b/util/grub-mkstandalone.c
index 8e2a2b8c2..4907d44c0 100644
--- a/util/grub-mkstandalone.c
+++ b/util/grub-mkstandalone.c
@@ -236,7 +236,7 @@ add_tar_file (const char *from,
       set_tar_value (hd.size, optr - tcn, 12);
       set_tar_value (hd.mtime, mtime, 12);
       hd.typeflag = 'L';
-      memcpy (hd.magic, "ustar  ", 7);
+      memcpy (hd.magic, MAGIC, sizeof (hd.magic));
       memcpy (hd.uname, "grub", 4);
       memcpy (hd.gname, "grub", 4);
 
@@ -266,7 +266,7 @@ add_tar_file (const char *from,
   set_tar_value (hd.size, size, 12);
   set_tar_value (hd.mtime, mtime, 12);
   hd.typeflag = '0';
-  memcpy (hd.magic, "ustar  ", 7);
+  memcpy (hd.magic, MAGIC, sizeof (hd.magic));
   memcpy (hd.uname, "grub", 4);
   memcpy (hd.gname, "grub", 4);
 
@@ -284,6 +284,7 @@ add_tar_file (const char *from,
   grub_util_fd_close (in);
 
   write_pad (size);
+  free (tcn);
 }
 
 int
diff --git a/util/grub-mount.c b/util/grub-mount.c
index 19de2e620..0d0fea5f2 100644
--- a/util/grub-mount.c
+++ b/util/grub-mount.c
@@ -516,6 +516,7 @@ argp_parser (int key, char *arg, struct argp_state *state)
 	      return 0;
 	    }
 	  grub_zfs_add_key (buf, real_size, 0);
+	  fclose (f);
 	}
       return 0;
 
@@ -546,7 +547,7 @@ argp_parser (int key, char *arg, struct argp_state *state)
     }
 
   images = xrealloc (images, (num_disks + 1) * sizeof (images[0]));
-  images[num_disks] = canonicalize_file_name (arg);
+  images[num_disks] = grub_canonicalize_file_name (arg);
   num_disks++;
 
   return 0;
diff --git a/util/grub-probe.c b/util/grub-probe.c
index ecb7b6bbd..6075cb3fc 100644
--- a/util/grub-probe.c
+++ b/util/grub-probe.c
@@ -262,7 +262,7 @@ probe (const char *path, char **device_names, char delim)
 
   if (path != NULL)
     {
-      grub_path = canonicalize_file_name (path);
+      grub_path = grub_canonicalize_file_name (path);
       if (! grub_path)
 	grub_util_error (_("failed to get canonical path of `%s'"), path);
       device_names = grub_guess_root_devices (grub_path);
@@ -295,6 +295,7 @@ probe (const char *path, char **device_names, char delim)
 	    }
 	  printf ("%s", disk);
 	  putchar (delim);
+	  free (disk);
 	}
       return;
     }
@@ -496,6 +497,7 @@ probe (const char *path, char **device_names, char delim)
 	{
 	  grub_util_fprint_full_disk_name (stdout, dev->disk->name, dev);
 	  putchar (delim);
+	  grub_device_close (dev);
 	  continue;
 	}
 
@@ -542,7 +544,7 @@ probe (const char *path, char **device_names, char delim)
       if (print == PRINT_IEEE1275_HINT)
 	{
 	  const char *osdev = grub_util_biosdisk_get_osdev (dev->disk);
-	  const char *ofpath = grub_util_devname_to_ofpath (osdev);
+	  char *ofpath = grub_util_devname_to_ofpath (osdev);
 	  const char *map;
 
 	  map = grub_util_biosdisk_get_compatibility_hint (dev->disk);
@@ -560,6 +562,7 @@ probe (const char *path, char **device_names, char delim)
 	      strcpy (p, ofpath);
 	      grub_util_fprint_full_disk_name (stdout, tmp, dev);
 	      free (tmp);
+	      free (ofpath);
 	      putchar (delim);
 	    }
 
@@ -725,11 +728,14 @@ help_filter (int key, const char *text, void *input __attribute__ ((unused)))
 
       case 't':
 	{
-	  char *ret, *t = get_targets_string ();
+	  char *ret, *t = get_targets_string (), *def;
 
-	  ret = xasprintf ("%s\n%s %s [default=%s]", _("print TARGET"),
-			    _("available targets:"), t, targets[print]);
+	  def = xasprintf (_("[default=%s]"), targets[print]);
+
+	  ret = xasprintf ("%s\n%s %s %s", _("print TARGET"),
+			    _("available targets:"), t, def);
 	  free (t);
+	  free (def);
 	  return ret;
 	}
 
diff --git a/util/grub-syslinux2cfg.c b/util/grub-syslinux2cfg.c
index f4fda6db9..85fa0da14 100644
--- a/util/grub-syslinux2cfg.c
+++ b/util/grub-syslinux2cfg.c
@@ -175,7 +175,7 @@ main (int argc, char *argv[])
   grub_host_init ();
 
   char *t, *inpfull, *rootfull, *res;
-  t = canonicalize_file_name (arguments.input);
+  t = grub_canonicalize_file_name (arguments.input);
   if (!t)
     {
       grub_util_error (_("cannot open `%s': %s"), arguments.input,
@@ -185,7 +185,7 @@ main (int argc, char *argv[])
   inpfull = xasprintf ("(host)/%s", t);
   free (t);
 
-  t = canonicalize_file_name (arguments.root ? : "/");
+  t = grub_canonicalize_file_name (arguments.root ? : "/");
   if (!t)
     {
       grub_util_error (_("cannot open `%s': %s"), arguments.root,
@@ -206,7 +206,7 @@ main (int argc, char *argv[])
       cwd = xstrdup (".");
     }
 
-  t = canonicalize_file_name (arguments.cwd ? : cwd);
+  t = grub_canonicalize_file_name (arguments.cwd ? : cwd);
   if (!t)
     {
       grub_util_error (_("cannot open `%s': %s"), arguments.root,
diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in
index ce2ec819d..93a90233e 100644
--- a/util/grub.d/00_header.in
+++ b/util/grub.d/00_header.in
@@ -25,7 +25,7 @@ grub_lang=`echo $LANG | cut -d . -f 1`
 export TEXTDOMAIN=@PACKAGE@
 export TEXTDOMAINDIR="@localedir@"
 
-. "@datadir@/@PACKAGE@/grub-mkconfig_lib"
+. "$pkgdatadir/grub-mkconfig_lib"
 
 # Do this as early as possible, since other commands might depend on it.
 # (e.g. the `loadfont' command might need lvm or raid modules)
diff --git a/util/grub.d/10_hurd.in b/util/grub.d/10_hurd.in
index 29b455423..59a9a48a2 100644
--- a/util/grub.d/10_hurd.in
+++ b/util/grub.d/10_hurd.in
@@ -24,7 +24,7 @@ datarootdir="@datarootdir@"
 export TEXTDOMAIN=@PACKAGE@
 export TEXTDOMAINDIR="@localedir@"
 
-. "@datadir@/@PACKAGE@/grub-mkconfig_lib"
+. "$pkgdatadir/grub-mkconfig_lib"
 
 CLASS="--class gnu --class os"
 
diff --git a/util/grub.d/10_illumos.in b/util/grub.d/10_illumos.in
index 0de616e89..a133e1b3f 100644
--- a/util/grub.d/10_illumos.in
+++ b/util/grub.d/10_illumos.in
@@ -20,7 +20,7 @@ set -e
 prefix="@prefix@"
 exec_prefix="@exec_prefix@"
 datarootdir="@datarootdir@"
-. "@datadir@/@PACKAGE@/grub-mkconfig_lib"
+. "$pkgdatadir/grub-mkconfig_lib"
 
 export TEXTDOMAIN=@PACKAGE@
 export TEXTDOMAINDIR="@localedir@"
diff --git a/util/grub.d/10_kfreebsd.in b/util/grub.d/10_kfreebsd.in
index ba7175bd7..9d8e8fd85 100644
--- a/util/grub.d/10_kfreebsd.in
+++ b/util/grub.d/10_kfreebsd.in
@@ -20,7 +20,7 @@ set -e
 prefix="@prefix@"
 exec_prefix="@exec_prefix@"
 datarootdir="@datarootdir@"
-. "@datadir@/@PACKAGE@/grub-mkconfig_lib"
+. "$pkgdatadir/grub-mkconfig_lib"
 
 export TEXTDOMAIN=@PACKAGE@
 export TEXTDOMAINDIR="@localedir@"
@@ -143,9 +143,12 @@ EOF
 EOF
 }
 
-list=`for i in /boot/kfreebsd-* /boot/kernel/kernel ; do
-        if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi
-      done`
+list=
+for i in /boot/kfreebsd-* /boot/kernel/kernel ; do
+  if grub_file_is_not_garbage "$i" ; then
+    list="$list $i"
+  fi
+done
 prepare_boot_cache=
 boot_device_id=
 title_correction_code=
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index d2e2a8fd3..859b608f6 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -21,7 +21,7 @@ prefix="@prefix@"
 exec_prefix="@exec_prefix@"
 datarootdir="@datarootdir@"
 
-. "@datadir@/@PACKAGE@/grub-mkconfig_lib"
+. "$pkgdatadir/grub-mkconfig_lib"
 
 export TEXTDOMAIN=@PACKAGE@
 export TEXTDOMAINDIR="@localedir@"
@@ -147,13 +147,15 @@ EOF
 machine=`uname -m`
 case "x$machine" in
     xi?86 | xx86_64)
-	list=`for i in /boot/vmlinuz-* /vmlinuz-* /boot/kernel-* ; do
-                  if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi
-              done` ;;
+	list=
+	for i in /boot/vmlinuz-* /vmlinuz-* /boot/kernel-* ; do
+	    if grub_file_is_not_garbage "$i" ; then list="$list $i" ; fi
+	done ;;
     *) 
-	list=`for i in /boot/vmlinuz-* /boot/vmlinux-* /vmlinuz-* /vmlinux-* /boot/kernel-* ; do
-                  if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi
-	     done` ;;
+	list=
+	for i in /boot/vmlinuz-* /boot/vmlinux-* /vmlinuz-* /vmlinux-* /boot/kernel-* ; do
+                  if grub_file_is_not_garbage "$i" ; then list="$list $i" ; fi
+	done ;;
 esac
 
 case "$machine" in
diff --git a/util/grub.d/10_netbsd.in b/util/grub.d/10_netbsd.in
index 9988a42bc..874f59969 100644
--- a/util/grub.d/10_netbsd.in
+++ b/util/grub.d/10_netbsd.in
@@ -20,7 +20,7 @@ set -e
 prefix="@prefix@"
 exec_prefix="@exec_prefix@"
 datarootdir="@datarootdir@"
-. "@datadir@/@PACKAGE@/grub-mkconfig_lib"
+. "$pkgdatadir/grub-mkconfig_lib"
 
 export TEXTDOMAIN=@PACKAGE@
 export TEXTDOMAINDIR="@localedir@"
diff --git a/util/grub.d/10_windows.in b/util/grub.d/10_windows.in
index 48bd95546..554c5614b 100644
--- a/util/grub.d/10_windows.in
+++ b/util/grub.d/10_windows.in
@@ -24,7 +24,7 @@ datarootdir="@datarootdir@"
 export TEXTDOMAIN=@PACKAGE@
 export TEXTDOMAINDIR="@localedir@"
 
-. "@datadir@/@PACKAGE@/grub-mkconfig_lib"
+. "$pkgdatadir/grub-mkconfig_lib"
 
 case "`uname 2>/dev/null`" in
   CYGWIN*)  ;;
diff --git a/util/grub.d/10_xnu.in b/util/grub.d/10_xnu.in
index 4270385f3..51ee2f427 100644
--- a/util/grub.d/10_xnu.in
+++ b/util/grub.d/10_xnu.in
@@ -24,7 +24,7 @@ datarootdir="@datarootdir@"
 export TEXTDOMAIN=@PACKAGE@
 export TEXTDOMAINDIR="@localedir@"
 
-. "@datadir@/@PACKAGE@/grub-mkconfig_lib"
+. "$pkgdatadir/grub-mkconfig_lib"
 
 osx_entry() {
     if [ x$2 = x32 ]; then
diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
index 2e777584c..f532fb98f 100644
--- a/util/grub.d/20_linux_xen.in
+++ b/util/grub.d/20_linux_xen.in
@@ -21,7 +21,7 @@ prefix="@prefix@"
 exec_prefix="@exec_prefix@"
 datarootdir="@datarootdir@"
 
-. "@datadir@/@PACKAGE@/grub-mkconfig_lib"
+. "$pkgdatadir/grub-mkconfig_lib"
 
 export TEXTDOMAIN=@PACKAGE@
 export TEXTDOMAINDIR="@localedir@"
@@ -137,7 +137,8 @@ EOF
 EOF
 }
 
-linux_list=`for i in /boot/vmlinu[xz]-* /vmlinu[xz]-* /boot/kernel-*; do
+linux_list=
+for i in /boot/vmlinu[xz]-* /vmlinu[xz]-* /boot/kernel-*; do
     if grub_file_is_not_garbage "$i"; then
     	basename=$(basename $i)
 	version=$(echo $basename | sed -e "s,^[^0-9]*-,,g")
@@ -149,9 +150,9 @@ linux_list=`for i in /boot/vmlinu[xz]-* /vmlinu[xz]-* /boot/kernel-*; do
 		break
 	    fi
 	done
-        if (grep -qx "CONFIG_XEN_DOM0=y" "${config}" 2> /dev/null || grep -qx "CONFIG_XEN_PRIVILEGED_GUEST=y" "${config}" 2> /dev/null); then echo -n "$i " ; fi
+        if (grep -qx "CONFIG_XEN_DOM0=y" "${config}" 2> /dev/null || grep -qx "CONFIG_XEN_PRIVILEGED_GUEST=y" "${config}" 2> /dev/null); then linux_list="$linux_list $i" ; fi
     fi
-    done`
+done
 if [ "x${linux_list}" = "x" ] ; then
     exit 0
 fi
@@ -165,9 +166,10 @@ file_is_not_sym () {
     esac
 }
 
-xen_list=`for i in /boot/xen*; do
-        if grub_file_is_not_garbage "$i" && file_is_not_sym "$i" ; then echo -n "$i " ; fi
-      done`
+xen_list=
+for i in /boot/xen*; do
+    if grub_file_is_not_garbage "$i" && file_is_not_sym "$i" ; then xen_list="$xen_list $i" ; fi
+done
 prepare_boot_cache=
 boot_device_id=
 
diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
index 6f38c82a5..5fc4f0c83 100644
--- a/util/grub.d/30_os-prober.in
+++ b/util/grub.d/30_os-prober.in
@@ -24,7 +24,7 @@ datarootdir="@datarootdir@"
 export TEXTDOMAIN=@PACKAGE@
 export TEXTDOMAINDIR="@localedir@"
 
-. "@datadir@/@PACKAGE@/grub-mkconfig_lib"
+. "$pkgdatadir/grub-mkconfig_lib"
 
 if [ "x${GRUB_DISABLE_OS_PROBER}" = "xtrue" ]; then
   exit 0
@@ -322,9 +322,8 @@ EOF
 EOF
     ;;
     *)
-      echo -n "  "
       # TRANSLATORS: %s is replaced by OS name.
-      gettext_printf "%s is not yet supported by grub-mkconfig.\n" "${LONGNAME}" >&2
+      gettext_printf "%s is not yet supported by grub-mkconfig.\n" "  ${LONGNAME}" >&2
     ;;
   esac
 done
diff --git a/util/misc.c b/util/misc.c
index b0e023ecd..b8ec69108 100644
--- a/util/misc.c
+++ b/util/misc.c
@@ -89,6 +89,8 @@ grub_util_get_image_size (const char *path)
   fseeko (f, 0, SEEK_END);
   
   sz = ftello (f);
+  if (sz < 0)
+    grub_util_error (_("cannot open `%s': %s"), path, strerror (errno));
   if (sz != (size_t) sz)
     grub_util_error (_("file `%s' is too big"), path);
   ret = (size_t) sz;
diff --git a/util/mkimage.c b/util/mkimage.c
index e6b799fd7..52265b557 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -55,6 +55,9 @@
 
 #define TARGET_NO_FIELD 0xffffffff
 
+/* use 2015-01-01T00:00:00+0000 as a stock timestamp */
+#define STABLE_EMBEDDING_TIMESTAMP 1420070400
+
 struct grub_install_image_target_desc
 {
   const char *dirname;
@@ -937,8 +940,8 @@ grub_install_get_image_target (const char *arg)
 {
   unsigned i, j;
   for (i = 0; i < ARRAY_SIZE (image_targets); i++)
-    for (j = 0; image_targets[i].names[j]
-	   && j < ARRAY_SIZE (image_targets[i].names); j++)
+    for (j = 0; j < ARRAY_SIZE (image_targets[i].names) &&
+		    image_targets[i].names[j]; j++)
       if (strcmp (arg, image_targets[i].names[j]) == 0)
 	return &image_targets[i];
   return NULL;
@@ -1278,6 +1281,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
       free (core_img);
       core_img = full_img;
       core_size = full_size;
+      free (decompress_img);
+      free (decompress_path);
     }
 
   switch (image_target->id)
@@ -1437,7 +1442,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	c->machine = grub_host_to_target16 (image_target->pe_target);
 
 	c->num_sections = grub_host_to_target16 (4);
-	c->time = grub_host_to_target32 (time (0));
+	c->time = grub_host_to_target32 (STABLE_EMBEDDING_TIMESTAMP);
 	c->characteristics = grub_host_to_target16 (GRUB_PE32_EXECUTABLE_IMAGE
 						    | GRUB_PE32_LINE_NUMS_STRIPPED
 						    | ((image_target->voidp_sizeof == 4)
@@ -1744,6 +1749,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
       free (core_img);
       core_img = rom_img;
       core_size = rom_size;
+      free (boot_img);
+      free (boot_path);
     }
     break;
     case IMAGE_QEMU_MIPS_FLASH:
@@ -1778,7 +1785,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
 
       memset (hdr, 0, sizeof (*hdr));
       hdr->ih_magic = grub_cpu_to_be32_compile_time (GRUB_UBOOT_IH_MAGIC);
-      hdr->ih_time = grub_cpu_to_be32 (time (0));
+      hdr->ih_time = grub_cpu_to_be32 (STABLE_EMBEDDING_TIMESTAMP);
       hdr->ih_size = grub_cpu_to_be32 (core_size);
       hdr->ih_load = grub_cpu_to_be32 (image_target->link_addr);
       hdr->ih_ep = grub_cpu_to_be32 (image_target->link_addr);
diff --git a/util/probe.c b/util/probe.c
index c389f5dcf..fa7ca34d1 100644
--- a/util/probe.c
+++ b/util/probe.c
@@ -73,7 +73,7 @@ grub_util_guess_bios_drive (const char *orig_path)
 {
   char *canon;
   char *ptr;
-  canon = canonicalize_file_name (orig_path);
+  canon = grub_canonicalize_file_name (orig_path);
   if (!canon)
     return NULL;
   ptr = strrchr (orig_path, '/');
@@ -102,7 +102,7 @@ grub_util_guess_efi_drive (const char *orig_path)
 {
   char *canon;
   char *ptr;
-  canon = canonicalize_file_name (orig_path);
+  canon = grub_canonicalize_file_name (orig_path);
   if (!canon)
     return NULL;
   ptr = strrchr (orig_path, '/');
@@ -131,7 +131,7 @@ grub_util_guess_baremetal_drive (const char *orig_path)
 {
   char *canon;
   char *ptr;
-  canon = canonicalize_file_name (orig_path);
+  canon = grub_canonicalize_file_name (orig_path);
   if (!canon)
     return NULL;
   ptr = strrchr (orig_path, '/');
diff --git a/util/render-label.c b/util/render-label.c
index 39663a8a7..91c080c9c 100644
--- a/util/render-label.c
+++ b/util/render-label.c
@@ -157,7 +157,7 @@ grub_util_render_label (const char *label_font,
   ieee1275_palette[cptr].a = 0xff;
 
   char * t;
-  t = canonicalize_file_name (label_font);
+  t = grub_canonicalize_file_name (label_font);
   if (!t)
     {
       grub_util_error (_("cannot open `%s': %s"), label_font,
diff --git a/util/setup.c b/util/setup.c
index 9fb91a82f..8f20e9983 100644
--- a/util/setup.c
+++ b/util/setup.c
@@ -322,7 +322,10 @@ SETUP (const char *dir,
 	  continue;
 	try_dev = grub_device_open (drive);
 	if (! try_dev)
-	  continue;
+	  {
+	    free (drive);
+	    continue;
+	  }
 	if (!found && try_dev->disk->id == dest_dev->disk->id
 	    && try_dev->disk->dev->id == dest_dev->disk->dev->id)
 	  {
@@ -526,7 +529,7 @@ SETUP (const char *dir,
     bl.block = bl.first_block;
     while (bl.block->len)
       {
-	grub_memset (bl.block, 0, sizeof (bl.block));
+	grub_memset (bl.block, 0, sizeof (*bl.block));
       
 	bl.block--;
 
@@ -667,15 +670,17 @@ unable_to_embed:
     if (dest_dev->disk->id != root_dev->disk->id
 	|| dest_dev->disk->dev->id != root_dev->disk->dev->id)
       {
-	const char *dest_ofpath;
+	char *dest_ofpath;
 	dest_ofpath
 	  = grub_util_devname_to_ofpath (grub_util_biosdisk_get_osdev (root_dev->disk));
+	/* FIXME handle NULL result */
 	grub_util_info ("dest_ofpath is `%s'", dest_ofpath);
 	strncpy (boot_devpath, dest_ofpath,
 		 GRUB_BOOT_MACHINE_BOOT_DEVPATH_END
 		 - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1);
 	boot_devpath[GRUB_BOOT_MACHINE_BOOT_DEVPATH_END
 		   - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1] = 0;
+	free (dest_ofpath);
       }
     else
       {