diff --git a/ChangeLog b/ChangeLog index 346c01b83..3e1ace4af 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,56 @@ +2013-12-03 Colin Watson + + Add a new timeout_style environment variable and a corresponding + GRUB_TIMEOUT_STYLE configuration key for grub-mkconfig. This + controls hidden-timeout handling more simply than the previous + arrangements, and pressing any hotkeys associated with menu entries + during the hidden timeout will now boot the corresponding menu entry + immediately. + + GRUB_HIDDEN_TIMEOUT= + GRUB_TIMEOUT= now + generates a warning, and if it shows the menu it will do so as if + the second timeout were not present. Other combinations are + translated into reasonable equivalents. + + Based loosely on work by Franz Hsieh. Fixes Ubuntu bug #1178618. + +2013-12-02 Vladimir Serbinenko + + * util/config.c: Add missing pointer adjustment. + Reported by: qwertial + +2013-11-30 Andrey Borzenkov + + * grub-core/kern/arm64/dl_helper.c: Include grub/arm64/reloc.h + directly, not via `cpu' link, to fix libgrub.pp generation. + +2013-11-30 Leif Lindholm + + New port arm64-efi. + +2013-11-30 Andrey Borzenkov + + * docs/grub.texi (sleep): Document exit codes. + +2013-11-30 Vladimir Serbinenko + + Ensure that -mno-unaligned-access or some equivalent option is used. + +2013-11-30 Vladimir Serbinenko + + * grub-core/lib/libgcrypt/mpi/longlong.h: Fix compilation error with + -march=armv3. + +2013-11-30 Vladimir Serbinenko + + Remove leftover GRUB_IA64_DL_TRAMP_SIZE. + +2013-11-29 Colin Watson + + * docs/grub-dev.texi (Font Metrics): Exclude @image command from DVI + builds, since we don't have an EPS version of font_char_metrics.png. + Add leading dot to image extension per the Texinfo documentation. + 2013-11-29 Colin Watson * util/grub-gen-asciih.c: Include FT_SYNTHESIS_H rather than diff --git a/INSTALL b/INSTALL index cb9df3077..ad27f3d88 100644 --- a/INSTALL +++ b/INSTALL @@ -18,6 +18,8 @@ configuring the GRUB. earlier versions not tested Note: clang 3.2 or later works for arm earlier versions not tested + Note: clang 3.3 or later works for arm64 + earlier versions have no arm64 support Note: clang 3.3 or later works for mips(el) earlier versions fail to generate .reginfo and hence gprel relocations fail. diff --git a/Makefile.util.def b/Makefile.util.def index 6114fe356..8169d22ba 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -156,6 +156,8 @@ library = { common = grub-core/io/gzio.c; common = grub-core/io/lzopio.c; common = grub-core/kern/ia64/dl_helper.c; + common = grub-core/kern/arm/dl_helper.c; + common = grub-core/kern/arm64/dl_helper.c; common = grub-core/lib/minilzo/minilzo.c; common = grub-core/lib/xzembed/xz_dec_bcj.c; common = grub-core/lib/xzembed/xz_dec_lzma2.c; @@ -177,8 +179,6 @@ program = { extra_dist = grub-core/osdep/unix/config.c; common = util/config.c; - common = grub-core/kern/arm/dl_helper.c; - extra_dist = util/grub-mkimagexx.c; ldadd = libgrubmods.a; @@ -535,8 +535,6 @@ program = { common = grub-core/kern/emu/hostfs.c; common = grub-core/disk/host.c; - common = grub-core/kern/arm/dl_helper.c; - common = util/resolve.c; common = grub-core/kern/emu/argp_common.c; @@ -581,8 +579,6 @@ program = { common = grub-core/kern/emu/hostfs.c; common = grub-core/disk/host.c; - common = grub-core/kern/arm/dl_helper.c; - common = util/resolve.c; common = grub-core/kern/emu/argp_common.c; @@ -618,8 +614,6 @@ program = { common = grub-core/osdep/config.c; common = util/config.c; - common = grub-core/kern/arm/dl_helper.c; - common = util/resolve.c; enable = noemu; common = grub-core/kern/emu/argp_common.c; @@ -655,8 +649,6 @@ program = { common = grub-core/osdep/config.c; common = util/config.c; - common = grub-core/kern/arm/dl_helper.c; - common = util/resolve.c; common = grub-core/kern/emu/argp_common.c; common = grub-core/osdep/init.c; diff --git a/acinclude.m4 b/acinclude.m4 index 78212133d..0e867e35c 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -474,23 +474,3 @@ dnl program. AC_DEFUN([grub_TRANSFORM],[dnl AC_SUBST(AS_TR_SH([$1]), [`AS_ECHO([$1]) | sed "$program_transform_name"`])dnl ]) - -dnl Check if the C compiler supports `-mno-unaligned-access'. -AC_DEFUN([grub_CHECK_NO_UNALIGNED_ACCESS],[ -[# foobar -nua_possible=yes] -AC_MSG_CHECKING([whether `$CC' supports `-mno-unaligned-access']) -AC_LANG_CONFTEST([AC_LANG_SOURCE([[ -int main() { - return 0; -} -]])]) - -[if eval "$ac_compile -S -mno-unaligned-access -o conftest.s" 2> /dev/null; then] - AC_MSG_RESULT([yes]) - [rm -f conftest.s -else - nua_possible=no] - AC_MSG_RESULT([no]) -[fi] -]) diff --git a/conf/Makefile.common b/conf/Makefile.common index c72d678bd..8a71f136e 100644 --- a/conf/Makefile.common +++ b/conf/Makefile.common @@ -15,6 +15,9 @@ if COND_arm CCASFLAGS_PLATFORM = -mthumb-interwork LDFLAGS_PLATFORM = -Wl,--wrap=__clear_cache endif +if COND_arm64 + CFLAGS_PLATFORM += -mcmodel=large +endif #FIXME: discover and check XEN headers CPPFLAGS_XEN = -I/usr/include diff --git a/configure.ac b/configure.ac index 48cc2de74..38219c3cc 100644 --- a/configure.ac +++ b/configure.ac @@ -99,6 +99,9 @@ case "$target_cpu" in arm*) target_cpu=arm; ;; + aarch64*) + target_cpu=arm64; + ;; esac # Specify the platform (such as firmware). @@ -120,6 +123,7 @@ if test "x$with_platform" = x; then mips-*) platform=arc ;; ia64-*) platform=efi ;; arm-*) platform=uboot ;; + arm64-*) platform=efi ;; *) AC_MSG_ERROR([unsupported CPU: "$target_cpu"]) ;; esac else @@ -160,6 +164,7 @@ case "$target_cpu"-"$platform" in mipsel-loongson) ;; arm-uboot) ;; arm-efi) ;; + arm64-efi) ;; *-emu) ;; *) AC_MSG_ERROR([platform "$platform" is not supported for target CPU "$target_cpu"]) ;; esac @@ -210,6 +215,7 @@ case "$platform" in esac case "$target_cpu" in arm) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_ARM=1" ;; + arm64) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_ARM64=1" ;; mips |mipsel) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS=1" ;; sparc64) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_SPARC64=1" ;; esac @@ -839,11 +845,26 @@ fi CFLAGS="$TARGET_CFLAGS" -# -mno-unaligned-access +# -mno-unaligned-access -mstrict-align if test "$target_cpu" = arm; then - grub_CHECK_NO_UNALIGNED_ACCESS - if test x"$nua_possible" = xyes; then - TARGET_CFLAGS="$TARGET_CFLAGS -mno-unaligned-access" + AC_CACHE_CHECK([for compile options to get strict alignment], [grub_cv_target_cc_strict_align], [ + grub_cv_target_cc_strict_align=unknown + for arg in -mno-unaligned-access "-Xclang -mstrict-align" -mstrict-align; do + CFLAGS="$TARGET_CFLAGS $arg -Werror" + LDFLAGS="$TARGET_LDFLAGS" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [flag=1], [flag=0]) + if test x"$flag" = x1; then + grub_cv_target_cc_strict_align="$arg" + break; + fi + done]) + + if test x"$grub_cv_target_cc_strict_align" = xunknown; then + AC_MSG_ERROR([couldnt instruct compiler not to use unaligned access]) + fi + TARGET_CFLAGS="$TARGET_CFLAGS $grub_cv_target_cc_strict_align" + if test x"$grub_cv_target_cc_strict_align" = x"-Xclang -mstrict-align"; then + TARGET_LDFLAGS="$TARGET_LDFLAGS -Qunused-arguments" fi fi @@ -1538,6 +1559,8 @@ AM_CONDITIONAL([COND_mipseb], [test x$target_cpu = xmips]) AM_CONDITIONAL([COND_arm], [test x$target_cpu = xarm ]) AM_CONDITIONAL([COND_arm_uboot], [test x$target_cpu = xarm -a x$platform = xuboot]) AM_CONDITIONAL([COND_arm_efi], [test x$target_cpu = xarm -a x$platform = xefi]) +AM_CONDITIONAL([COND_arm64], [test x$target_cpu = xarm64 ]) +AM_CONDITIONAL([COND_arm64_efi], [test x$target_cpu = xarm64 -a x$platform = xefi]) AM_CONDITIONAL([COND_HOST_HURD], [test x$host_kernel = xhurd]) AM_CONDITIONAL([COND_HOST_LINUX], [test x$host_kernel = xlinux]) diff --git a/debian/patches/gfxpayload_dynamic.patch b/debian/patches/gfxpayload_dynamic.patch index 1aaa3b11f..27b0cad71 100644 --- a/debian/patches/gfxpayload_dynamic.patch +++ b/debian/patches/gfxpayload_dynamic.patch @@ -5,13 +5,13 @@ Description: Add configure option to enable gfxpayload=keep dynamically Author: Evan Broder Author: Colin Watson Forwarded: no -Last-Update: 2013-11-29 +Last-Update: 2013-12-03 Index: b/configure.ac =================================================================== --- a/configure.ac +++ b/configure.ac -@@ -1425,6 +1425,17 @@ +@@ -1446,6 +1446,17 @@ fi AC_SUBST([QUICK_BOOT]) @@ -33,7 +33,7 @@ Index: b/grub-core/Makefile.core.def =================================================================== --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def -@@ -881,6 +881,15 @@ +@@ -894,6 +894,15 @@ }; module = { diff --git a/debian/patches/grub.cfg_400.patch b/debian/patches/grub.cfg_400.patch index f09afc0fb..9209cd5fc 100644 --- a/debian/patches/grub.cfg_400.patch +++ b/debian/patches/grub.cfg_400.patch @@ -2,7 +2,7 @@ Index: b/util/grub-mkconfig.in =================================================================== --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in -@@ -254,6 +254,10 @@ +@@ -256,6 +256,10 @@ esac done diff --git a/debian/patches/install_efi_ubuntu_flavours.patch b/debian/patches/install_efi_ubuntu_flavours.patch index e419e41da..283881a3d 100644 --- a/debian/patches/install_efi_ubuntu_flavours.patch +++ b/debian/patches/install_efi_ubuntu_flavours.patch @@ -5,13 +5,13 @@ Description: Cope with Kubuntu setting GRUB_DISTRIBUTOR Author: Colin Watson Bug-Ubuntu: https://bugs.launchpad.net/bugs/1242417 Forwarded: not-needed -Last-Update: 2013-11-26 +Last-Update: 2013-12-03 Index: b/util/grub-install.c =================================================================== --- a/util/grub-install.c +++ b/util/grub-install.c -@@ -939,6 +939,8 @@ +@@ -945,6 +945,8 @@ */ char *t; efi_distributor = bootloader_id; diff --git a/debian/patches/install_locale_langpack.patch b/debian/patches/install_locale_langpack.patch index 92e6357e1..00229f078 100644 --- a/debian/patches/install_locale_langpack.patch +++ b/debian/patches/install_locale_langpack.patch @@ -2,7 +2,7 @@ Description: Prefer translations from Ubuntu language packs if available Author: Colin Watson Bug-Ubuntu: https://bugs.launchpad.net/bugs/537998 Forwarded: not-needed -Last-Update: 2013-11-29 +Last-Update: 2013-12-03 Index: b/util/grub-install-common.c =================================================================== @@ -61,7 +61,7 @@ Index: b/util/grub-install-common.c } static struct -@@ -731,12 +739,14 @@ +@@ -732,12 +740,14 @@ { char *srcd = grub_util_path_concat (2, src, "po"); copy_by_ext (srcd, dst_locale, ".mo", 0); @@ -77,7 +77,7 @@ Index: b/util/grub-install-common.c for (i = 0; i < install_locales.n_entries; i++) { -@@ -755,6 +765,19 @@ +@@ -756,6 +766,19 @@ } free (srcf); srcf = grub_util_path_concat_ext (4, @@ -97,7 +97,7 @@ Index: b/util/grub-install-common.c locale_dir, install_locales.entries[i], "LC_MESSAGES", -@@ -769,6 +792,8 @@ +@@ -770,6 +793,8 @@ grub_util_error (_("cannot find locale `%s'"), install_locales.entries[i]); } diff --git a/debian/patches/install_signed.patch b/debian/patches/install_signed.patch index ffb97ed9f..3a5f12374 100644 --- a/debian/patches/install_signed.patch +++ b/debian/patches/install_signed.patch @@ -3,7 +3,7 @@ Author: Colin Watson Author: Stéphane Graber Author: Steve Langasek Forwarded: no -Last-Update: 2013-11-26 +Last-Update: 2013-12-03 Index: b/util/grub-install.c =================================================================== @@ -58,7 +58,7 @@ Index: b/util/grub-install.c {0, 0, 0, 0, 0, 0} }; -@@ -686,7 +705,8 @@ +@@ -689,7 +708,8 @@ { int is_efi = 0; const char *efi_distributor = NULL; @@ -68,7 +68,7 @@ Index: b/util/grub-install.c char **grub_devices; grub_fs_t grub_fs; grub_device_t grub_dev = NULL; -@@ -919,6 +939,27 @@ +@@ -925,6 +945,31 @@ */ char *t; efi_distributor = bootloader_id; @@ -90,13 +90,17 @@ Index: b/util/grub-install.c + efi_suffix = "arm"; + efi_suffix_upper = "ARM"; + break; ++ case GRUB_INSTALL_PLATFORM_ARM64_EFI: ++ efi_suffix = "arm64"; ++ efi_suffix_upper = "AARCH64"; ++ break; + default: + break; + } if (removable) { /* The specification makes stricter requirements of removable -@@ -927,48 +968,16 @@ +@@ -933,54 +978,16 @@ must have a specific file name depending on the architecture. */ efi_distributor = "BOOT"; @@ -114,6 +118,9 @@ Index: b/util/grub-install.c - case GRUB_INSTALL_PLATFORM_ARM_EFI: - efi_file = "BOOTARM.EFI"; - break; +- case GRUB_INSTALL_PLATFORM_ARM64_EFI: +- efi_file = "BOOTAARCH64.EFI"; +- break; - default: - grub_util_error ("%s", _("You've found a bug")); - break; @@ -141,6 +148,9 @@ Index: b/util/grub-install.c - case GRUB_INSTALL_PLATFORM_ARM_EFI: - efi_file = "grubarm.efi"; - break; +- case GRUB_INSTALL_PLATFORM_ARM64_EFI: +- efi_file = "grubarm64.efi"; +- break; - default: - efi_file = "grub.efi"; - break; @@ -149,7 +159,7 @@ Index: b/util/grub-install.c } t = grub_util_path_concat (3, efidir, "EFI", efi_distributor); free (efidir); -@@ -1098,6 +1107,31 @@ +@@ -1110,6 +1117,31 @@ } } @@ -181,7 +191,7 @@ Index: b/util/grub-install.c if (!have_abstractions) { if ((disk_module && grub_strcmp (disk_module, "biosdisk") != 0) -@@ -1105,7 +1139,8 @@ +@@ -1117,7 +1149,8 @@ || (!install_drive && platform != GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275) || (install_drive && !is_same_disk (grub_drives[0], install_drive)) @@ -191,7 +201,7 @@ Index: b/util/grub-install.c { char *uuid = NULL; /* generic method (used on coreboot and ata mod). */ -@@ -1533,7 +1568,47 @@ +@@ -1549,7 +1582,47 @@ case GRUB_INSTALL_PLATFORM_IA64_EFI: { char *dst = grub_util_path_concat (2, efidir, efi_file); diff --git a/debian/patches/install_stage2_confusion.patch b/debian/patches/install_stage2_confusion.patch index 408c48c9b..0545e742c 100644 --- a/debian/patches/install_stage2_confusion.patch +++ b/debian/patches/install_stage2_confusion.patch @@ -2,7 +2,7 @@ Description: If GRUB Legacy is still around, tell packaging to ignore it Author: Colin Watson Bug-Debian: http://bugs.debian.org/586143 Forwarded: not-needed -Last-Update: 2013-11-26 +Last-Update: 2013-12-03 Index: b/util/grub-install.c =================================================================== @@ -16,7 +16,7 @@ Index: b/util/grub-install.c #include -@@ -1427,6 +1428,19 @@ +@@ -1442,6 +1443,19 @@ grub_util_bios_setup (platdir, "boot.img", "core.img", install_drive, force, fs_probe, allow_floppy); diff --git a/debian/patches/linuxefi.patch b/debian/patches/linuxefi.patch index 0c75a4585..bff280268 100644 --- a/debian/patches/linuxefi.patch +++ b/debian/patches/linuxefi.patch @@ -2,13 +2,13 @@ Description: Add "linuxefi" loader which avoids ExitBootServices Author: Matthew Garrett Origin: vendor, http://pkgs.fedoraproject.org/cgit/grub2.git/tree/grub2-linuxefi.patch Forwarded: no -Last-Update: 2013-11-29 +Last-Update: 2013-12-03 Index: b/grub-core/Makefile.core.def =================================================================== --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def -@@ -1674,6 +1674,14 @@ +@@ -1687,6 +1687,14 @@ }; module = { diff --git a/debian/patches/linuxefi_amd64_only.patch b/debian/patches/linuxefi_amd64_only.patch index 4e0763a07..c2b5c160d 100644 --- a/debian/patches/linuxefi_amd64_only.patch +++ b/debian/patches/linuxefi_amd64_only.patch @@ -1,13 +1,13 @@ Description: Only build linuxefi on amd64 Author: Colin Watson Forwarded: no -Last-Update: 2013-11-29 +Last-Update: 2013-12-03 Index: b/grub-core/Makefile.core.def =================================================================== --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def -@@ -1677,7 +1677,6 @@ +@@ -1690,7 +1690,6 @@ name = linuxefi; efi = loader/i386/efi/linux.c; efi = lib/cmdline.c; diff --git a/debian/patches/maybe_quiet.patch b/debian/patches/maybe_quiet.patch index 4b18f1c62..272a1daeb 100644 --- a/debian/patches/maybe_quiet.patch +++ b/debian/patches/maybe_quiet.patch @@ -25,7 +25,7 @@ Author: Colin Watson Bug-Ubuntu: https://bugs.launchpad.net/bugs/386922 Bug-Ubuntu: https://bugs.launchpad.net/bugs/861048 Forwarded: (partial) http://lists.gnu.org/archive/html/grub-devel/2009-09/msg00056.html -Last-Update: 2013-11-26 +Last-Update: 2013-12-03 Index: b/config.h.in =================================================================== @@ -44,7 +44,7 @@ Index: b/configure.ac =================================================================== --- a/configure.ac +++ b/configure.ac -@@ -1403,6 +1403,17 @@ +@@ -1424,6 +1424,17 @@ fi AC_SUBST([UBUNTU_RECOVERY]) @@ -62,7 +62,7 @@ Index: b/configure.ac LIBS="" AC_SUBST([FONT_SOURCE]) -@@ -1650,5 +1661,10 @@ +@@ -1673,5 +1684,10 @@ else echo "With liblzma from $LIBLZMA (support for XZ-compressed mips images)" fi @@ -276,7 +276,7 @@ Index: b/grub-core/normal/menu.c =================================================================== --- a/grub-core/normal/menu.c +++ b/grub-core/normal/menu.c -@@ -674,12 +674,18 @@ +@@ -807,12 +807,18 @@ /* Callback invoked immediately before a menu entry is executed. */ static void @@ -296,7 +296,7 @@ Index: b/grub-core/normal/menu.c } /* Callback invoked when a default menu entry executed because of a timeout -@@ -727,6 +733,9 @@ +@@ -860,6 +866,9 @@ int boot_entry; grub_menu_entry_t e; int auto_boot; @@ -306,7 +306,7 @@ Index: b/grub-core/normal/menu.c boot_entry = run_menu (menu, nested, &auto_boot); if (boot_entry < 0) -@@ -736,7 +745,11 @@ +@@ -869,7 +878,11 @@ if (! e) continue; /* Menu is empty. */ diff --git a/debian/patches/mkconfig_ubuntu_recovery.patch b/debian/patches/mkconfig_ubuntu_recovery.patch index 790a8dd6b..ded4fbbc0 100644 --- a/debian/patches/mkconfig_ubuntu_recovery.patch +++ b/debian/patches/mkconfig_ubuntu_recovery.patch @@ -6,13 +6,13 @@ Description: "single" -> "recovery" when friendly-recovery is installed Author: Colin Watson Author: Stéphane Graber Forwarded: no -Last-Update: 2013-11-26 +Last-Update: 2013-12-03 Index: b/configure.ac =================================================================== --- a/configure.ac +++ b/configure.ac -@@ -1392,6 +1392,17 @@ +@@ -1413,6 +1413,17 @@ AC_SUBST([LIBZFS]) AC_SUBST([LIBNVPAIR]) diff --git a/debian/patches/quick_boot.patch b/debian/patches/quick_boot.patch index cb82d33a8..56d9ec0df 100644 --- a/debian/patches/quick_boot.patch +++ b/debian/patches/quick_boot.patch @@ -14,13 +14,13 @@ Description: Add configure option to bypass boot menu if possible Author: Colin Watson Author: Richard Laager Forwarded: no -Last-Update: 2013-11-26 +Last-Update: 2013-12-03 Index: b/configure.ac =================================================================== --- a/configure.ac +++ b/configure.ac -@@ -1414,6 +1414,17 @@ +@@ -1435,6 +1435,17 @@ fi AC_SUBST([QUIET_BOOT]) @@ -42,7 +42,7 @@ Index: b/docs/grub.texi =================================================================== --- a/docs/grub.texi +++ b/docs/grub.texi -@@ -1487,6 +1487,15 @@ +@@ -1490,6 +1490,15 @@ Each module will be loaded as early as possible, at the start of @file{grub.cfg}. @@ -57,12 +57,47 @@ Index: b/docs/grub.texi + @end table - For more detailed customisation of @command{grub-mkconfig}'s output, you may + The following options are still accepted for compatibility with existing +Index: b/grub-core/normal/menu.c +=================================================================== +--- a/grub-core/normal/menu.c ++++ b/grub-core/normal/menu.c +@@ -604,6 +604,30 @@ + static struct grub_term_coordinate *pos; + int entry = -1; + ++ if (timeout == 0) ++ { ++ /* If modifier key statuses can't be detected without a delay, ++ then a hidden timeout of zero cannot be interrupted in any way, ++ which is not very helpful. Bump it to three seconds in this ++ case to give the user a fighting chance. */ ++ grub_term_input_t term; ++ int nterms = 0; ++ int mods_detectable = 1; ++ ++ FOR_ACTIVE_TERM_INPUTS(term) ++ { ++ if (!term->getkeystatus) ++ { ++ mods_detectable = 0; ++ break; ++ } ++ else ++ nterms++; ++ } ++ if (!mods_detectable || !nterms) ++ timeout = 3; ++ } ++ + if (timeout_style == TIMEOUT_STYLE_COUNTDOWN && timeout) + { + pos = grub_term_save_pos (); Index: b/util/grub-mkconfig.in =================================================================== --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in -@@ -229,7 +229,8 @@ +@@ -231,7 +231,8 @@ GRUB_ENABLE_CRYPTODISK \ GRUB_BADRAM \ GRUB_OS_PROBER_SKIP_LIST \ @@ -125,23 +160,58 @@ Index: b/util/grub.d/00_header.in function load_video { EOF if [ -n "${GRUB_VIDEO_BACKEND}" ]; then -@@ -282,7 +309,15 @@ +@@ -282,6 +309,12 @@ make_timeout () { -- if [ "x${1}" != "x" ] ; then -+ if [ "$quick_boot" = 1 ] ; then -+ cat << EOF -+if [ "\${recordfail}" = 1 ]; then ++ cat << EOF ++if [ "\${recordfail}" = 1 ] ; then + set timeout=${GRUB_RECORDFAIL_TIMEOUT:--1} ++fi +else ++EOF + if [ "x${1}${3}" != "x" ] ; then + if [ "x${3}" != "x" ] ; then + timeout="${2}" +@@ -304,26 +337,29 @@ + verbose= + fi + cat << EOF +-if [ x\$feature_timeout_style = xy ] ; then +- set timeout_style=${style} +- set timeout=${timeout} ++ if [ x\$feature_timeout_style = xy ] ; then ++ set timeout_style=${style} ++ set timeout=${timeout} + EOF + if [ "x${style}" != "xmenu" ] ; then + cat << EOF +-# Fallback hidden-timeout code in case the timeout_style feature is +-# unavailable. +-elif sleep${verbose} --interruptible ${timeout} ; then +- set timeout=0 ++ # Fallback hidden-timeout code in case the timeout_style feature is ++ # unavailable. ++ elif sleep${verbose} --interruptible ${timeout} ; then ++ set timeout=0 + EOF + fi + cat << EOF +-fi ++ fi + EOF + else + cat << EOF +-set timeout=${2} + set timeout=${2} + EOF + fi ++ cat << EOF +fi +EOF -+ elif [ "x${1}" != "x" ] ; then - if [ "x${GRUB_HIDDEN_TIMEOUT_QUIET}" = "xtrue" ] ; then - verbose= - else + } + + if [ "x$GRUB_BUTTON_CMOS_ADDRESS" != "x" ]; then Index: b/util/grub.d/10_linux.in =================================================================== --- a/util/grub.d/10_linux.in @@ -168,7 +238,7 @@ Index: b/util/grub.d/30_os-prober.in =================================================================== --- a/util/grub.d/30_os-prober.in +++ b/util/grub.d/30_os-prober.in -@@ -20,28 +20,90 @@ +@@ -20,12 +20,26 @@ prefix="@prefix@" exec_prefix="@exec_prefix@" datarootdir="@datarootdir@" @@ -181,77 +251,21 @@ Index: b/util/grub.d/30_os-prober.in +found_other_os= + -+make_timeout () { -+ if [ "x${found_other_os}" = "x" ] ; then -+ if [ "x${1}" != "x" ] ; then -+ if [ "x${GRUB_HIDDEN_TIMEOUT_QUIET}" = "xtrue" ] ; then -+ verbose= -+ else -+ verbose=" --verbose" -+ fi -+ -+ if [ "x${1}" = "x0" ] ; then -+ cat < /dev/null`" -o -z "`which linux-boot-prober 2> /dev/null`" ] ; then - # missing os-prober and/or linux-boot-prober -+ adjust_timeout - exit 0 - fi - - OSPROBED="`os-prober | tr ' ' '^' | paste -s -d ' '`" - if [ -z "${OSPROBED}" ] ; then - # empty os-prober output, nothing doing -+ adjust_timeout - exit 0 +@@ -42,6 +56,7 @@ fi osx_entry() { @@ -259,7 +273,7 @@ Index: b/util/grub.d/30_os-prober.in if [ x$2 = x32 ]; then # TRANSLATORS: it refers to kernel architecture (32-bit) bitstr="$(gettext "(32-bit)")" -@@ -158,6 +220,7 @@ +@@ -158,6 +173,7 @@ ;; esac @@ -267,7 +281,7 @@ Index: b/util/grub.d/30_os-prober.in onstr="$(gettext_printf "(on %s)" "${DEVICE}")" cat << EOF menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class windows --class os \$menuentry_id_option 'osprober-chain-$(grub_get_device_id "${DEVICE}")' { -@@ -188,6 +251,7 @@ +@@ -188,6 +204,7 @@ ;; efi) @@ -275,7 +289,7 @@ Index: b/util/grub.d/30_os-prober.in EFIPATH=${DEVICE#*@} DEVICE=${DEVICE%@*} onstr="$(gettext_printf "(on %s)" "${DEVICE}")" -@@ -236,6 +300,7 @@ +@@ -236,6 +253,7 @@ [ "${prepare_boot_cache}" ] || continue fi @@ -283,7 +297,7 @@ Index: b/util/grub.d/30_os-prober.in onstr="$(gettext_printf "(on %s)" "${DEVICE}")" recovery_params="$(echo "${LPARAMS}" | grep 'single\|recovery')" || true counter=1 -@@ -302,6 +367,7 @@ +@@ -302,6 +320,7 @@ osx_entry xnu_kernel64 64 ;; hurd) @@ -291,7 +305,7 @@ Index: b/util/grub.d/30_os-prober.in onstr="$(gettext_printf "(on %s)" "${DEVICE}")" cat << EOF menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class hurd --class gnu --class os \$menuentry_id_option 'osprober-gnuhurd-/boot/gnumach.gz-false-$(grub_get_device_id "${DEVICE}")' { -@@ -345,3 +411,5 @@ +@@ -345,3 +364,5 @@ ;; esac done diff --git a/debian/patches/vt_handoff.patch b/debian/patches/vt_handoff.patch index 376398b1d..6a89cbadc 100644 --- a/debian/patches/vt_handoff.patch +++ b/debian/patches/vt_handoff.patch @@ -4,13 +4,13 @@ Description: Add configure option to use vt.handoff=7 Author: Colin Watson Author: Andy Whitcroft Forwarded: not-needed -Last-Update: 2013-11-26 +Last-Update: 2013-12-03 Index: b/configure.ac =================================================================== --- a/configure.ac +++ b/configure.ac -@@ -1436,6 +1436,17 @@ +@@ -1457,6 +1457,17 @@ fi AC_SUBST([GFXPAYLOAD_DYNAMIC]) diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi index ff79e51b0..c79685052 100644 --- a/docs/grub-dev.texi +++ b/docs/grub-dev.texi @@ -1812,7 +1812,9 @@ right edges of two adjacent glyphs. The @strong{device width} field determines the effective leading value that is used to render the font. @end itemize -@image{font_char_metrics,,,,png} +@ifnottex +@image{font_char_metrics,,,,.png} +@end ifnottex An illustration of how the various font metrics apply to characters. diff --git a/docs/grub.texi b/docs/grub.texi index a68c79700..37c2e8909 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -1298,23 +1298,26 @@ a key is pressed. The default is @samp{5}. Set to @samp{0} to boot immediately without displaying the menu, or to @samp{-1} to wait indefinitely. -@item GRUB_HIDDEN_TIMEOUT -Wait this many seconds for @key{ESC} to be pressed before displaying the menu. -If no @key{ESC} is pressed during that time, display the menu for the number of -seconds specified in GRUB_TIMEOUT before booting the default entry. We expect -that most people who use GRUB_HIDDEN_TIMEOUT will want to have GRUB_TIMEOUT set -to @samp{0} so that the menu is not displayed at all unless @key{ESC} is -pressed. -Unset by default. +If @samp{GRUB_TIMEOUT_STYLE} is set to @samp{countdown} or @samp{hidden}, +the timeout is instead counted before the menu is displayed. -@item GRUB_HIDDEN_TIMEOUT_QUIET -In conjunction with @samp{GRUB_HIDDEN_TIMEOUT}, set this to @samp{true} to -suppress the verbose countdown while waiting for a key to be pressed before -displaying the menu. Unset by default. +@item GRUB_TIMEOUT_STYLE +If this option is unset or set to @samp{menu}, then GRUB will display the +menu and then wait for the timeout set by @samp{GRUB_TIMEOUT} to expire +before booting the default entry. Pressing a key interrupts the timeout. + +If this option is set to @samp{countdown} or @samp{hidden}, then, before +displaying the menu, GRUB will wait for the timeout set by +@samp{GRUB_TIMEOUT} to expire. If @key{ESC} is pressed during that time, it +will display the menu and wait for input. If a hotkey associated with a +menu entry is pressed, it will boot the associated menu entry immediately. +If the timeout expires before either of these happens, it will boot the +default entry. In the @samp{countdown} case, it will show a one-line +indication of the remaining time. @item GRUB_DEFAULT_BUTTON @itemx GRUB_TIMEOUT_BUTTON -@itemx GRUB_HIDDEN_TIMEOUT_BUTTON +@itemx GRUB_TIMEOUT_STYLE_BUTTON @itemx GRUB_BUTTON_CMOS_ADDRESS Variants of the corresponding variables without the @samp{_BUTTON} suffix, used to support vendor-specific power buttons. @xref{Vendor power-on keys}. @@ -1498,6 +1501,44 @@ This option is only effective when GRUB was configured with the @end table +The following options are still accepted for compatibility with existing +configurations, but have better replacements: + +@table @samp +@item GRUB_HIDDEN_TIMEOUT +Wait this many seconds before displaying the menu. If @key{ESC} is pressed +during that time, display the menu and wait for input according to +@samp{GRUB_TIMEOUT}. If a hotkey associated with a menu entry is pressed, +boot the associated menu entry immediately. If the timeout expires before +either of these happens, display the menu for the number of seconds +specified in @samp{GRUB_TIMEOUT} before booting the default entry. + +If you set @samp{GRUB_HIDDEN_TIMEOUT}, you should also set +@samp{GRUB_TIMEOUT=0} so that the menu is not displayed at all unless +@key{ESC} is pressed. + +This option is unset by default, and is deprecated in favour of the less +confusing @samp{GRUB_TIMEOUT_STYLE=countdown} or +@samp{GRUB_TIMEOUT_STYLE=hidden}. + +@item GRUB_HIDDEN_TIMEOUT_QUIET +In conjunction with @samp{GRUB_HIDDEN_TIMEOUT}, set this to @samp{true} to +suppress the verbose countdown while waiting for a key to be pressed before +displaying the menu. + +This option is unset by default, and is deprecated in favour of the less +confusing @samp{GRUB_TIMEOUT_STYLE=countdown}. + +@item GRUB_HIDDEN_TIMEOUT_BUTTON +Variant of @samp{GRUB_HIDDEN_TIMEOUT}, used to support vendor-specific power +buttons. @xref{Vendor power-on keys}. + +This option is unset by default, and is deprecated in favour of the less +confusing @samp{GRUB_TIMEOUT_STYLE=countdown} or +@samp{GRUB_TIMEOUT_STYLE=hidden}. + +@end table + For more detailed customisation of @command{grub-mkconfig}'s output, you may edit the scripts in @file{/etc/grub.d} directly. @file{/etc/grub.d/40_custom} is particularly useful for adding entire custom @@ -2486,15 +2527,16 @@ menu requires several fancy features of your terminal. @node Vendor power-on keys @chapter Using GRUB with vendor power-on keys -Some laptop vendors provide an additional power-on button which boots another -OS. GRUB supports such buttons with the @samp{GRUB_TIMEOUT_BUTTON}, -@samp{GRUB_DEFAULT_BUTTON}, @samp{GRUB_HIDDEN_TIMEOUT_BUTTON} and +Some laptop vendors provide an additional power-on button which boots +another OS. GRUB supports such buttons with the @samp{GRUB_TIMEOUT_BUTTON}, +@samp{GRUB_TIMEOUT_STYLE_BUTTON}, @samp{GRUB_DEFAULT_BUTTON}, and @samp{GRUB_BUTTON_CMOS_ADDRESS} variables in default/grub (@pxref{Simple -configuration}). @samp{GRUB_TIMEOUT_BUTTON}, @samp{GRUB_DEFAULT_BUTTON} and -@samp{GRUB_HIDDEN_TIMEOUT_BUTTON} are used instead of the corresponding -variables without the @samp{_BUTTON} suffix when powered on using the special -button. @samp{GRUB_BUTTON_CMOS_ADDRESS} is vendor-specific and partially -model-specific. Values known to the GRUB team are: +configuration}). @samp{GRUB_TIMEOUT_BUTTON}, +@samp{GRUB_TIMEOUT_STYLE_BUTTON}, and @samp{GRUB_DEFAULT_BUTTON} are used +instead of the corresponding variables without the @samp{_BUTTON} suffix +when powered on using the special button. @samp{GRUB_BUTTON_CMOS_ADDRESS} +is vendor-specific and partially model-specific. Values known to the GRUB +team are: @table @key @item Dell XPS M1330M @@ -3039,6 +3081,7 @@ These variables have special meaning to GRUB. * superusers:: * theme:: * timeout:: +* timeout_style:: @end menu @@ -3471,8 +3514,21 @@ keyboard input before booting the default menu entry. A timeout of @samp{0} means to boot the default entry immediately without displaying the menu; a timeout of @samp{-1} (or unset) means to wait indefinitely. -This variable is often set by @samp{GRUB_TIMEOUT} or -@samp{GRUB_HIDDEN_TIMEOUT} (@pxref{Simple configuration}). +If @samp{timeout_style} (@pxref{timeout_style}) is set to @samp{countdown} +or @samp{hidden}, the timeout is instead counted before the menu is +displayed. + +This variable is often set by @samp{GRUB_TIMEOUT} (@pxref{Simple +configuration}). + + +@node timeout_style +@subsection timeout_style + +This variable may be set to @samp{menu}, @samp{countdown}, or @samp{hidden} +to control the way in which the timeout (@pxref{timeout}) interacts with +displaying the menu. See the documentation of @samp{GRUB_TIMEOUT_STYLE} +(@pxref{Simple configuration}) for details. @node Environment block @@ -4892,7 +4948,8 @@ Alias for @code{hashsum --hash sha512 arg @dots{}}. See command @command{hashsum @deffn Command sleep [@option{--verbose}] [@option{--interruptible}] count Sleep for @var{count} seconds. If option @option{--interruptible} is given, allow @key{ESC} to interrupt sleep. With @option{--verbose} show countdown -of remaining seconds. +of remaining seconds. Exit code is set to 0 if timeout expired and to 1 +if timeout was interrupted by @key{ESC}. @end deffn diff --git a/gentpl.py b/gentpl.py index 2c2afad93..1d4583c68 100644 --- a/gentpl.py +++ b/gentpl.py @@ -29,7 +29,7 @@ GRUB_PLATFORMS = [ "emu", "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot", "i386_xen", "x86_64_xen", "mips_loongson", "sparc64_ieee1275", "powerpc_ieee1275", "mips_arc", "ia64_efi", - "mips_qemu_mips", "arm_uboot", "arm_efi" ] + "mips_qemu_mips", "arm_uboot", "arm_efi", "arm64_efi" ] GROUPS = {} @@ -43,9 +43,10 @@ GROUPS["mips"] = [ "mips_loongson", "mips_qemu_mips", "mips_arc" ] GROUPS["sparc64"] = [ "sparc64_ieee1275" ] GROUPS["powerpc"] = [ "powerpc_ieee1275" ] GROUPS["arm"] = [ "arm_uboot", "arm_efi" ] +GROUPS["arm64"] = [ "arm64_efi" ] # Groups based on firmware -GROUPS["efi"] = [ "i386_efi", "x86_64_efi", "ia64_efi", "arm_efi" ] +GROUPS["efi"] = [ "i386_efi", "x86_64_efi", "ia64_efi", "arm_efi", "arm64_efi" ] GROUPS["ieee1275"] = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275" ] GROUPS["uboot"] = [ "arm_uboot" ] GROUPS["xen"] = [ "i386_xen", "x86_64_xen" ] @@ -71,7 +72,7 @@ GROUPS["terminfomodule"] = GRUB_PLATFORMS[:]; for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i) # Flattened Device Trees (FDT) -GROUPS["fdt"] = [ "arm_uboot", "arm_efi" ] +GROUPS["fdt"] = [ "arm64_efi", "arm_uboot", "arm_efi" ] # Miscelaneous groups schedulded to disappear in future GROUPS["i386_coreboot_multiboot_qemu"] = ["i386_coreboot", "i386_multiboot", "i386_qemu"] diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 20f00a3c2..9bc68f77b 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -234,6 +234,11 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h endif +if COND_arm64_efi +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h +endif + if COND_emu KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/datetime.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/misc.h diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index a42c91248..6a7a66cf9 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -67,6 +67,9 @@ kernel = { arm_efi_ldflags = '-Wl,-r,-d'; arm_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; + arm64_efi_ldflags = '-Wl,-r,-d'; + arm64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; + i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000'; @@ -106,6 +109,7 @@ kernel = { powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S; arm_uboot_startup = kern/arm/uboot/startup.S; arm_efi_startup = kern/arm/efi/startup.S; + arm64_efi_startup = kern/arm64/efi/startup.S; common = kern/command.c; common = kern/corecmd.c; @@ -194,6 +198,8 @@ kernel = { arm_efi = kern/arm/efi/init.c; arm_efi = kern/arm/efi/misc.c; + arm64_efi = kern/arm/efi/init.c; + i386_pc = kern/i386/pc/init.c; i386_pc = kern/i386/pc/mmap.c; i386_pc = term/i386/pc/console.c; @@ -254,6 +260,11 @@ kernel = { arm = kern/arm/cache.c; arm = kern/arm/misc.S; + arm64 = kern/arm64/cache.c; + arm64 = kern/arm64/cache_flush.S; + arm64 = kern/arm64/dl.c; + arm64 = kern/arm64/dl_helper.c; + emu = disk/host.c; emu = kern/emu/cache_s.S; emu = kern/emu/hostdisk.c; @@ -743,6 +754,7 @@ module = { enable = mips_arc; enable = ia64_efi; enable = arm_efi; + enable = arm64_efi; enable = arm_uboot; }; @@ -838,6 +850,7 @@ module = { ia64_efi = lib/efi/reboot.c; x86_64_efi = lib/efi/reboot.c; arm_efi = lib/efi/reboot.c; + arm64_efi = lib/efi/reboot.c; powerpc_ieee1275 = lib/ieee1275/reboot.c; sparc64_ieee1275 = lib/ieee1275/reboot.c; mips_arc = lib/mips/arc/reboot.c; @@ -1716,6 +1729,7 @@ module = { enable = x86; enable = ia64_efi; enable = arm_efi; + enable = arm64_efi; enable = mips; }; diff --git a/grub-core/kern/arm64/cache.c b/grub-core/kern/arm64/cache.c new file mode 100644 index 000000000..b84383da1 --- /dev/null +++ b/grub-core/kern/arm64/cache.c @@ -0,0 +1,63 @@ +/* + * 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 . + */ + +#include +#include + +static grub_int64_t dlinesz; +static grub_int64_t ilinesz; + +/* Prototypes for asm functions. */ +void grub_arch_clean_dcache_range (grub_addr_t beg, grub_addr_t end, + grub_uint64_t line_size); +void grub_arch_invalidate_icache_range (grub_addr_t beg, grub_addr_t end, + grub_uint64_t line_size); + +static void +probe_caches (void) +{ + grub_uint64_t cache_type; + + /* Read Cache Type Register */ + asm volatile ("mrs %0, ctr_el0": "=r"(cache_type)); + + dlinesz = 4 << ((cache_type >> 16) & 0xf); + ilinesz = 4 << (cache_type & 0xf); + + grub_dprintf("cache", "D$ line size: %lld\n", (long long) dlinesz); + grub_dprintf("cache", "I$ line size: %lld\n", (long long) ilinesz); +} + +void +grub_arch_sync_caches (void *address, grub_size_t len) +{ + grub_uint64_t start, end, max_align; + + if (dlinesz == 0) + probe_caches(); + if (dlinesz == 0) + grub_fatal ("Unknown cache line size!"); + + max_align = dlinesz > ilinesz ? dlinesz : ilinesz; + + start = ALIGN_DOWN ((grub_uint64_t) address, max_align); + end = ALIGN_UP ((grub_uint64_t) address + len, max_align); + + grub_arch_clean_dcache_range (start, end, dlinesz); + grub_arch_invalidate_icache_range (start, end, ilinesz); +} diff --git a/grub-core/kern/arm64/cache_flush.S b/grub-core/kern/arm64/cache_flush.S new file mode 100644 index 000000000..e064f7ece --- /dev/null +++ b/grub-core/kern/arm64/cache_flush.S @@ -0,0 +1,55 @@ +/* + * 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 . + */ + +#include + + .file "cache_flush.S" + .text + +/* + * Simple cache maintenance functions + */ + +// x0 - *beg (inclusive) +// x1 - *end (exclusive) +// x2 - line size +FUNCTION(grub_arch_clean_dcache_range) + // Clean data cache for range to point-of-unification +1: cmp x0, x1 + b.ge 2f + dc cvau, x0 // Clean Virtual Address to PoU + add x0, x0, x2 // Next line + b 1b +2: dsb ish + isb + ret + +// x0 - *beg (inclusive) +// x1 - *end (exclusive) +// x2 - line size +FUNCTION(grub_arch_invalidate_icache_range) + // Invalidate instruction cache for range to point-of-unification +1: cmp x0, x1 + b.ge 2f + ic ivau, x0 // Invalidate Virtual Address to PoU + add x0, x0, x2 // Next line + b 1b + // Branch predictor invalidation not needed on AArch64 +2: dsb ish + isb + ret diff --git a/grub-core/kern/arm64/dl.c b/grub-core/kern/arm64/dl.c new file mode 100644 index 000000000..afd0de2f3 --- /dev/null +++ b/grub-core/kern/arm64/dl.c @@ -0,0 +1,199 @@ +/* dl.c - arch-dependent part of loadable module support */ +/* + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * Check if EHDR is a valid ELF header. + */ +grub_err_t +grub_arch_dl_check_header (void *ehdr) +{ + Elf_Ehdr *e = ehdr; + + /* Check the magic numbers. */ + if (e->e_ident[EI_CLASS] != ELFCLASS64 + || e->e_ident[EI_DATA] != ELFDATA2LSB || e->e_machine != EM_AARCH64) + return grub_error (GRUB_ERR_BAD_OS, + N_("invalid arch-dependent ELF magic")); + + return GRUB_ERR_NONE; +} + +/* + * Unified function for both REL and RELA + */ +static grub_err_t +do_relX (Elf_Shdr * relhdr, Elf_Ehdr * e, grub_dl_t mod) +{ + grub_err_t retval; + grub_dl_segment_t segment; + Elf_Rel *rel; + Elf_Rela *rela; + Elf_Sym *symbol; + int i, entnum; + unsigned long long entsize; + + /* Find the target segment for this relocation section. */ + for (segment = mod->segment ; segment != 0 ; segment = segment->next) + if (segment->section == relhdr->sh_info) + break; + if (!segment) + return grub_error (GRUB_ERR_EOF, N_("relocation segment not found")); + + rel = (Elf_Rel *) ((grub_addr_t) e + relhdr->sh_offset); + rela = (Elf_Rela *) rel; + if (relhdr->sh_type == SHT_RELA) + entsize = sizeof (Elf_Rela); + else + entsize = sizeof (Elf_Rel); + + entnum = relhdr->sh_size / entsize; + retval = GRUB_ERR_NONE; + + grub_dprintf("dl", "Processing %d relocation entries.\n", entnum); + + /* Step through all relocations */ + for (i = 0, symbol = mod->symtab; i < entnum; i++) + { + void *place; + grub_uint64_t sym_addr, symidx, reltype; + + if (rel->r_offset >= segment->size) + return grub_error (GRUB_ERR_BAD_MODULE, + "reloc offset is out of the segment"); + + symidx = ELF_R_SYM (rel->r_info); + reltype = ELF_R_TYPE (rel->r_info); + + sym_addr = symbol[symidx].st_value; + if (relhdr->sh_type == SHT_RELA) + sym_addr += rela->r_addend; + + place = (void *) ((grub_addr_t) segment->addr + rel->r_offset); + + switch (reltype) + { + case R_AARCH64_ABS64: + { + grub_uint64_t *abs_place = place; + + grub_dprintf ("dl", " reloc_abs64 %p => 0x%016llx\n", + place, (unsigned long long) sym_addr); + + *abs_place = (grub_uint64_t) sym_addr; + } + break; + case R_AARCH64_CALL26: + case R_AARCH64_JUMP26: + retval = grub_arm64_reloc_xxxx26 (place, sym_addr); + break; + default: + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("relocation 0x%x is not implemented yet"), + reltype); + } + + if (retval != GRUB_ERR_NONE) + break; + + rel = (Elf_Rel *) ((grub_addr_t) rel + entsize); + rela++; + } + + return retval; +} + +/* + * Verify that provided ELF header contains reference to a symbol table + */ +static int +has_symtab (Elf_Ehdr * e) +{ + int i; + Elf_Shdr *s; + + for (i = 0, s = (Elf_Shdr *) ((grub_addr_t) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *) ((grub_addr_t) s + e->e_shentsize)) + if (s->sh_type == SHT_SYMTAB) + return 1; + + return 0; +} + +/* + * grub_arch_dl_relocate_symbols(): + * Locates the relocations section of the ELF object, and calls + * do_relX() to deal with it. + */ +grub_err_t +grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) +{ + Elf_Ehdr *e = ehdr; + Elf_Shdr *s; + unsigned i; + + if (!has_symtab (e)) + return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table")); + +#define FIRST_SHDR(x) ((Elf_Shdr *) ((grub_addr_t)(x) + (x)->e_shoff)) +#define NEXT_SHDR(x, y) ((Elf_Shdr *) ((grub_addr_t)(y) + (x)->e_shentsize)) + + for (i = 0, s = FIRST_SHDR (e); i < e->e_shnum; i++, s = NEXT_SHDR (e, s)) + { + grub_err_t ret; + + switch (s->sh_type) + { + case SHT_REL: + case SHT_RELA: + { + ret = do_relX (s, e, mod); + if (ret != GRUB_ERR_NONE) + return ret; + } + break; + case SHT_ARM_ATTRIBUTES: + case SHT_NOBITS: + case SHT_NULL: + case SHT_PROGBITS: + case SHT_SYMTAB: + case SHT_STRTAB: + break; + default: + { + grub_dprintf ("dl", "unhandled section_type: %d (0x%08x)\n", + s->sh_type, s->sh_type); + return GRUB_ERR_NOT_IMPLEMENTED_YET; + }; + } + } + +#undef FIRST_SHDR +#undef NEXT_SHDR + + return GRUB_ERR_NONE; +} diff --git a/grub-core/kern/arm64/dl_helper.c b/grub-core/kern/arm64/dl_helper.c new file mode 100644 index 000000000..6f99087e3 --- /dev/null +++ b/grub-core/kern/arm64/dl_helper.c @@ -0,0 +1,70 @@ +/* dl_helper.c - relocation helper functions for modules and grub-mkimage */ +/* + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include + +static grub_ssize_t +sign_compress_offset (grub_ssize_t offset, int bitpos) +{ + return offset & ((1LL << (bitpos + 1)) - 1); +} + +/* + * grub_arm64_reloc_xxxx26(): + * + * JUMP26/CALL26 relocations for B and BL instructions. + */ + +grub_err_t +grub_arm64_reloc_xxxx26 (grub_uint32_t *place, Elf64_Addr adjust) +{ + grub_uint32_t insword, insmask; + grub_ssize_t offset; + const grub_ssize_t offset_low = -(1 << 27), offset_high = (1 << 27) - 1; + + insword = grub_le_to_cpu32 (*place); + insmask = 0xfc000000; + + offset = adjust; +#ifndef GRUB_UTIL + offset -= (grub_addr_t) place; +#endif + + if ((offset < offset_low) || (offset > offset_high)) + { + return grub_error (GRUB_ERR_BAD_MODULE, + N_("CALL26 Relocation out of range")); + } + + grub_dprintf ("dl", " reloc_xxxx64 %p %c= 0x%llx\n", + place, offset > 0 ? '+' : '-', + offset < 0 ? (long long) -(unsigned long long) offset : offset); + + offset = sign_compress_offset (offset, 27) >> 2; + + *place = grub_cpu_to_le32 ((insword & insmask) | offset); + + return GRUB_ERR_NONE; +} diff --git a/grub-core/kern/arm64/efi/startup.S b/grub-core/kern/arm64/efi/startup.S new file mode 100644 index 000000000..666a7ee3c --- /dev/null +++ b/grub-core/kern/arm64/efi/startup.S @@ -0,0 +1,39 @@ +/* + * 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 . + */ + +#include + + .file "startup.S" + .text +FUNCTION(_start) + /* + * EFI_SYSTEM_TABLE and EFI_HANDLE are passed in x1/x0. + */ + ldr x2, efi_image_handle_val + str x0, [x2] + ldr x2, efi_system_table_val + str x1, [x2] + ldr x2, grub_main_val + br x2 +grub_main_val: + .quad EXT_C(grub_main) +efi_system_table_val: + .quad EXT_C(grub_efi_system_table) +efi_image_handle_val: + .quad EXT_C(grub_efi_image_handle) + diff --git a/grub-core/kern/ia64/dl.c b/grub-core/kern/ia64/dl.c index 957ceaae6..91a2645ce 100644 --- a/grub-core/kern/ia64/dl.c +++ b/grub-core/kern/ia64/dl.c @@ -115,7 +115,8 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) grub_uint64_t noff; grub_ia64_make_trampoline (tr, value); noff = ((char *) tr - (char *) (addr & ~3)) >> 4; - tr = (struct grub_ia64_trampoline *) ((char *) tr + GRUB_IA64_DL_TRAMP_SIZE); + tr++; + if (noff & ~MASK19) return grub_error (GRUB_ERR_BAD_OS, "trampoline offset too big (%lx)", noff); diff --git a/grub-core/kern/ia64/dl_helper.c b/grub-core/kern/ia64/dl_helper.c index 515e323ad..0bebe60e0 100644 --- a/grub-core/kern/ia64/dl_helper.c +++ b/grub-core/kern/ia64/dl_helper.c @@ -152,8 +152,6 @@ static const grub_uint8_t jump[0x20] = void grub_ia64_make_trampoline (struct grub_ia64_trampoline *tr, grub_uint64_t addr) { - COMPILE_TIME_ASSERT (sizeof (struct grub_ia64_trampoline) - == GRUB_IA64_DL_TRAMP_SIZE); grub_memcpy (tr->nop, nopm, sizeof (tr->nop)); tr->addr_hi[0] = ((addr & 0xc00000) >> 16); tr->addr_hi[1] = (addr >> 24) & 0xff; diff --git a/grub-core/lib/arm64/setjmp.S b/grub-core/lib/arm64/setjmp.S new file mode 100644 index 000000000..adaafe40f --- /dev/null +++ b/grub-core/lib/arm64/setjmp.S @@ -0,0 +1,53 @@ +/* + * 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 . + */ + +#include + + .file "setjmp.S" + .text + +/* + * int grub_setjmp (grub_jmp_buf env) + */ +FUNCTION(grub_setjmp) + stp x19, x20, [x0], #16 + stp x21, x22, [x0], #16 + stp x23, x24, [x0], #16 + stp x25, x26, [x0], #16 + stp x27, x28, [x0], #16 + stp x29, x30, [x0], #16 + mov x1, sp + str x1, [x0] + mov x0, #0 + ret + +/* + * int grub_longjmp (grub_jmp_buf env, int val) + */ +FUNCTION(grub_longjmp) + ldp x19, x20, [x0], #16 + ldp x21, x22, [x0], #16 + ldp x23, x24, [x0], #16 + ldp x25, x26, [x0], #16 + ldp x27, x28, [x0], #16 + ldp x29, x30, [x0], #16 + ldr x2, [x0] + mov sp, x2 + cmp x1, #0 + csel x0, x1, x0, ne + ret diff --git a/grub-core/lib/efi/halt.c b/grub-core/lib/efi/halt.c index ce93db39f..e9441c844 100644 --- a/grub-core/lib/efi/halt.c +++ b/grub-core/lib/efi/halt.c @@ -29,7 +29,7 @@ void grub_halt (void) { grub_machine_fini (GRUB_LOADER_FLAG_NORETURN); -#if !defined(__ia64__) && !defined(__arm__) +#if !defined(__ia64__) && !defined(__arm__) && !defined(__aarch64__) grub_acpi_halt (); #endif efi_call_4 (grub_efi_system_table->runtime_services->reset_system, diff --git a/grub-core/lib/libgcrypt/mpi/longlong.h b/grub-core/lib/libgcrypt/mpi/longlong.h index 6f8dda7df..b3fce0958 100644 --- a/grub-core/lib/libgcrypt/mpi/longlong.h +++ b/grub-core/lib/libgcrypt/mpi/longlong.h @@ -247,7 +247,7 @@ extern UDItype __udiv_qrnnd (); "=r" ((xl)) \ : "r" ((USItype)(a)), \ "r" ((USItype)(b)) \ - : "r0", "r1", "r2" __CLOBBER_CC) + : "r0", "r1", "r2" __AND_CLOBBER_CC) #else /* __ARM_ARCH >= 4 */ #define umul_ppmm(xh, xl, a, b) \ __asm__ ("@ Inlined umul_ppmm\n" \ diff --git a/grub-core/lib/setjmp.S b/grub-core/lib/setjmp.S index feb7b431c..f6e4905e2 100644 --- a/grub-core/lib/setjmp.S +++ b/grub-core/lib/setjmp.S @@ -13,6 +13,8 @@ #include "./ia64/longjmp.S" #elif defined(__arm__) #include "./arm/setjmp.S" +#elif defined(__aarch64__) +#include "./arm64/setjmp.S" #else #error "Unknown target cpu type" #endif diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c index 1cd2347e9..43be11a6a 100644 --- a/grub-core/normal/main.c +++ b/grub-core/normal/main.c @@ -534,7 +534,7 @@ static const char *features[] = { "feature_chainloader_bpb", "feature_ntldr", "feature_platform_search_hint", "feature_default_font_path", "feature_all_video_module", "feature_menuentry_id", "feature_menuentry_options", "feature_200_final", - "feature_nativedisk_cmd" + "feature_nativedisk_cmd", "feature_timeout_style" }; GRUB_MOD_INIT(normal) diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c index 21077fbb3..f6379de88 100644 --- a/grub-core/normal/menu.c +++ b/grub-core/normal/menu.c @@ -40,6 +40,22 @@ grub_err_t (*grub_gfxmenu_try_hook) (int entry, grub_menu_t menu, int nested) = NULL; +enum timeout_style { + TIMEOUT_STYLE_MENU, + TIMEOUT_STYLE_COUNTDOWN, + TIMEOUT_STYLE_HIDDEN +}; + +struct timeout_style_name { + const char *name; + enum timeout_style style; +} timeout_style_names[] = { + {"menu", TIMEOUT_STYLE_MENU}, + {"countdown", TIMEOUT_STYLE_COUNTDOWN}, + {"hidden", TIMEOUT_STYLE_HIDDEN}, + {NULL, 0} +}; + /* Wait until the user pushes any key so that the user can see what happened. */ void @@ -70,6 +86,40 @@ grub_menu_get_entry (grub_menu_t menu, int no) return e; } +/* Get the index of a menu entry associated with a given hotkey, or -1. */ +static int +get_entry_index_by_hotkey (grub_menu_t menu, int hotkey) +{ + grub_menu_entry_t entry; + int i; + + for (i = 0, entry = menu->entry_list; i < menu->size; + i++, entry = entry->next) + if (entry->hotkey == hotkey) + return i; + + return -1; +} + +/* Return the timeout style. If the variable "timeout_style" is not set or + invalid, default to TIMEOUT_STYLE_MENU. */ +static enum timeout_style +get_timeout_style (void) +{ + const char *val; + struct timeout_style_name *style_name; + + val = grub_env_get ("timeout_style"); + if (!val) + return TIMEOUT_STYLE_MENU; + + for (style_name = timeout_style_names; style_name->name; style_name++) + if (grub_strcmp (style_name->name, val) == 0) + return style_name->style; + + return TIMEOUT_STYLE_MENU; +} + /* Return the current timeout. If the variable "timeout" is not set or invalid, return -1. */ int @@ -488,6 +538,33 @@ get_entry_number (grub_menu_t menu, const char *name) return entry; } +/* Check whether a second has elapsed since the last tick. If so, adjust + the timer and return 1; otherwise, return 0. */ +static int +has_second_elapsed (grub_uint64_t *saved_time) +{ + grub_uint64_t current_time; + + current_time = grub_get_time_ms (); + if (current_time - *saved_time >= 1000) + { + *saved_time = current_time; + return 1; + } + else + return 0; +} + +static void +print_countdown (struct grub_term_coordinate *pos, int n) +{ + grub_term_restore_pos (pos); + /* NOTE: Do not remove the trailing space characters. + They are required to clear the line. */ + grub_printf ("%d ", n); + grub_refresh (); +} + #define GRUB_MENU_PAGE_SIZE 10 /* Show the menu and handle menu entry selection. Returns the menu entry @@ -502,6 +579,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) grub_uint64_t saved_time; int default_entry, current_entry; int timeout; + enum timeout_style timeout_style; default_entry = get_entry_number (menu, "default"); @@ -510,8 +588,95 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) if (default_entry < 0 || default_entry >= menu->size) default_entry = 0; + timeout = grub_menu_get_timeout (); + if (timeout < 0) + /* If there is no timeout, the "countdown" and "hidden" styles result in + the system doing nothing and providing no or very little indication + why. Technically this is what the user asked for, but it's not very + useful and likely to be a source of confusion, so we disallow this. */ + grub_env_unset ("timeout_style"); + + timeout_style = get_timeout_style (); + + if (timeout_style == TIMEOUT_STYLE_COUNTDOWN + || timeout_style == TIMEOUT_STYLE_HIDDEN) + { + static struct grub_term_coordinate *pos; + int entry = -1; + + if (timeout == 0) + { + /* If modifier key statuses can't be detected without a delay, + then a hidden timeout of zero cannot be interrupted in any way, + which is not very helpful. Bump it to three seconds in this + case to give the user a fighting chance. */ + grub_term_input_t term; + int nterms = 0; + int mods_detectable = 1; + + FOR_ACTIVE_TERM_INPUTS(term) + { + if (!term->getkeystatus) + { + mods_detectable = 0; + break; + } + else + nterms++; + } + if (!mods_detectable || !nterms) + timeout = 3; + } + + if (timeout_style == TIMEOUT_STYLE_COUNTDOWN && timeout) + { + pos = grub_term_save_pos (); + print_countdown (pos, timeout); + } + + /* Enter interruptible sleep until Escape or a menu hotkey is pressed, + or the timeout expires. */ + saved_time = grub_get_time_ms (); + while (1) + { + int key; + + key = grub_getkey_noblock (); + if (key != GRUB_TERM_NO_KEY) + { + entry = get_entry_index_by_hotkey (menu, key); + if (entry >= 0) + break; + } + if (key == GRUB_TERM_ESC) + { + timeout = -1; + break; + } + + if (timeout > 0 && has_second_elapsed (&saved_time)) + { + timeout--; + if (timeout_style == TIMEOUT_STYLE_COUNTDOWN) + print_countdown (pos, timeout); + } + + if (timeout == 0) + /* We will fall through to auto-booting the default entry. */ + break; + } + + grub_env_unset ("timeout"); + grub_env_unset ("timeout_style"); + if (entry >= 0) + { + *auto_boot = 0; + return entry; + } + } + /* If timeout is 0, drawing is pointless (and ugly). */ - if (grub_menu_get_timeout () == 0) + if (timeout == 0) { *auto_boot = 1; return default_entry; @@ -540,18 +705,11 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) if (grub_normal_exit_level) return -1; - if (timeout > 0) + if (timeout > 0 && has_second_elapsed (&saved_time)) { - grub_uint64_t current_time; - - current_time = grub_get_time_ms (); - if (current_time - saved_time >= 1000) - { - timeout--; - grub_menu_set_timeout (timeout); - saved_time = current_time; - menu_print_timeout (timeout); - } + timeout--; + grub_menu_set_timeout (timeout); + menu_print_timeout (timeout); } if (timeout == 0) @@ -653,16 +811,15 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) default: { - grub_menu_entry_t entry; - int i; - for (i = 0, entry = menu->entry_list; i < menu->size; - i++, entry = entry->next) - if (entry->hotkey == c) - { - menu_fini (); - *auto_boot = 0; - return i; - } + int entry; + + entry = get_entry_index_by_hotkey (menu, c); + if (entry >= 0) + { + menu_fini (); + *auto_boot = 0; + return entry; + } } break; } diff --git a/include/grub/arm64/efi/memory.h b/include/grub/arm64/efi/memory.h new file mode 100644 index 000000000..c9a61bb77 --- /dev/null +++ b/include/grub/arm64/efi/memory.h @@ -0,0 +1 @@ +#include diff --git a/include/grub/arm64/reloc.h b/include/grub/arm64/reloc.h new file mode 100644 index 000000000..606d71c77 --- /dev/null +++ b/include/grub/arm64/reloc.h @@ -0,0 +1,24 @@ +/* + * 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 . + */ + +#ifndef GRUB_ARM64_RELOC_H +#define GRUB_ARM64_RELOC_H 1 + +grub_err_t grub_arm64_reloc_xxxx26 (grub_uint32_t *target, Elf64_Addr sym_addr); + +#endif diff --git a/include/grub/arm64/setjmp.h b/include/grub/arm64/setjmp.h new file mode 100644 index 000000000..3ff7dfbf3 --- /dev/null +++ b/include/grub/arm64/setjmp.h @@ -0,0 +1,27 @@ +/* + * 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 . + */ + +#ifndef GRUB_SETJMP_CPU_HEADER +#define GRUB_SETJMP_CPU_HEADER 1 + +typedef unsigned long long grub_jmp_buf[13]; + +int grub_setjmp (grub_jmp_buf env) RETURNS_TWICE; +void grub_longjmp (grub_jmp_buf env, int val) __attribute__ ((noreturn)); + +#endif /* ! GRUB_SETJMP_CPU_HEADER */ diff --git a/include/grub/arm64/time.h b/include/grub/arm64/time.h new file mode 100644 index 000000000..4128506cb --- /dev/null +++ b/include/grub/arm64/time.h @@ -0,0 +1,29 @@ +/* + * 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 . + */ + +#ifndef KERNEL_CPU_TIME_HEADER +#define KERNEL_CPU_TIME_HEADER 1 + +static __inline void +grub_cpu_idle (void) +{ + /* FIXME: this can't work until we handle interrupts. */ +/* __asm__ __volatile__ ("wfi"); */ +} + +#endif /* ! KERNEL_CPU_TIME_HEADER */ diff --git a/include/grub/arm64/types.h b/include/grub/arm64/types.h new file mode 100644 index 000000000..d132c5eab --- /dev/null +++ b/include/grub/arm64/types.h @@ -0,0 +1,34 @@ +/* + * 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 . + */ + +#ifndef GRUB_TYPES_CPU_HEADER +#define GRUB_TYPES_CPU_HEADER 1 + +/* The size of void *. */ +#define GRUB_TARGET_SIZEOF_VOID_P 8 + +/* The size of long. */ +#define GRUB_TARGET_SIZEOF_LONG 8 + +/* currently only support little-endian. */ +#undef GRUB_TARGET_WORDS_BIGENDIAN + +/* Unaligned accesses only supported if MMU enabled */ +#undef GRUB_HAVE_UNALIGNED_ACCESS + +#endif /* ! GRUB_TYPES_CPU_HEADER */ diff --git a/include/grub/dl.h b/include/grub/dl.h index 11fc77568..d1d20d9d2 100644 --- a/include/grub/dl.h +++ b/include/grub/dl.h @@ -240,7 +240,6 @@ void grub_arch_dl_init_linker (void); #endif #define GRUB_IA64_DL_TRAMP_ALIGN 16 -#define GRUB_IA64_DL_TRAMP_SIZE 48 #define GRUB_IA64_DL_GOT_ALIGN 16 grub_err_t diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h index f7503406c..3af09111a 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h @@ -1534,7 +1534,8 @@ struct grub_efi_block_io }; typedef struct grub_efi_block_io grub_efi_block_io_t; -#if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) +#if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \ + || defined (__aarch64__) #define efi_call_0(func) func() #define efi_call_1(func, a) func(a) diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h index 7cacabd45..4adea603b 100644 --- a/include/grub/efi/pe32.h +++ b/include/grub/efi/pe32.h @@ -67,6 +67,7 @@ struct grub_pe32_coff_header #define GRUB_PE32_MACHINE_IA64 0x200 #define GRUB_PE32_MACHINE_X86_64 0x8664 #define GRUB_PE32_MACHINE_ARMTHUMB_MIXED 0x01c2 +#define GRUB_PE32_MACHINE_ARM64 0xAA64 #define GRUB_PE32_RELOCS_STRIPPED 0x0001 #define GRUB_PE32_EXECUTABLE_IMAGE 0x0002 diff --git a/include/grub/elf.h b/include/grub/elf.h index f64d6a891..140d24d02 100644 --- a/include/grub/elf.h +++ b/include/grub/elf.h @@ -246,6 +246,7 @@ typedef struct #define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ #define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ #define EM_NUM 95 +#define EM_AARCH64 183 /* ARM 64-bit architecture */ /* If it is necessary to assign new unofficial EM_* values, please pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the @@ -2062,6 +2063,21 @@ typedef Elf32_Addr Elf32_Conflict; #define SHT_ARM_ATTRIBUTES (SHT_LOPROC + 3) /* ARM attributes section. */ +/* AArch64 relocs. */ +#define R_AARCH64_NONE 0 /* No relocation. */ +#define R_AARCH64_ABS64 257 /* Direct 64 bit. */ +#define R_AARCH64_ABS32 258 /* Direct 32 bit. */ +#define R_AARCH64_JUMP26 282 /* 26-bit relative. */ +#define R_AARCH64_CALL26 283 /* 26-bit relative. */ +#define R_AARCH64_COPY 1024 /* Copy symbol at runtime. */ +#define R_AARCH64_GLOB_DAT 1025 /* Create GOT entry. */ +#define R_AARCH64_JUMP_SLOT 1026 /* Create PLT entry. */ +#define R_AARCH64_RELATIVE 1027 /* Adjust by program base. */ +#define R_AARCH64_TLS_DTPMOD64 1028 /* Module number, 64 bit. */ +#define R_AARCH64_TLS_DTPREL64 1029 /* Module-relative offset, 64 bit. */ +#define R_AARCH64_TLS_TPREL64 1030 /* TP-relative offset, 64 bit. */ +#define R_AARCH64_TLSDESC 1031 /* TLS Descriptor. */ + /* ARM relocs. */ #define R_ARM_NONE 0 /* No reloc */ #define R_ARM_PC24 1 /* PC relative 26 bit branch */ diff --git a/include/grub/util/install.h b/include/grub/util/install.h index 5cb33fc5e..9bf3e5f13 100644 --- a/include/grub/util/install.h +++ b/include/grub/util/install.h @@ -92,6 +92,7 @@ enum grub_install_plat GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS, GRUB_INSTALL_PLATFORM_I386_XEN, GRUB_INSTALL_PLATFORM_X86_64_XEN, + GRUB_INSTALL_PLATFORM_ARM64_EFI, GRUB_INSTALL_PLATFORM_MAX }; diff --git a/util/config.c b/util/config.c index f313714db..e7474c6d1 100644 --- a/util/config.c +++ b/util/config.c @@ -47,6 +47,9 @@ grub_util_parse_config (FILE *f, struct grub_util_config *cfg, int simple) { char *optr; enum { NONE, SNGLQUOT, DBLQUOT } state; + + ptr += sizeof ("GRUB_DISTRIBUTOR=") - 1; + if (simple) { free (cfg->grub_distributor); diff --git a/util/grub-install-common.c b/util/grub-install-common.c index 387fe3fde..75190a853 100644 --- a/util/grub-install-common.c +++ b/util/grub-install-common.c @@ -644,6 +644,7 @@ static struct [GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275] = { "powerpc", "ieee1275" }, [GRUB_INSTALL_PLATFORM_IA64_EFI] = { "ia64", "efi" }, [GRUB_INSTALL_PLATFORM_ARM_EFI] = { "arm", "efi" }, + [GRUB_INSTALL_PLATFORM_ARM64_EFI] = { "arm64", "efi" }, [GRUB_INSTALL_PLATFORM_ARM_UBOOT] = { "arm", "uboot" }, }; diff --git a/util/grub-install.c b/util/grub-install.c index c194c8fe3..6c1f6989f 100644 --- a/util/grub-install.c +++ b/util/grub-install.c @@ -287,6 +287,8 @@ get_default_platform (void) return "ia64-efi"; #elif defined (__arm__) return "arm-uboot"; +#elif defined (__aarch64__) + return "arm64-efi"; #elif defined (__amd64__) || defined (__x86_64__) || defined (__i386__) return grub_install_get_default_x86_platform (); #else @@ -420,6 +422,7 @@ have_bootdev (enum grub_install_plat pl) case GRUB_INSTALL_PLATFORM_X86_64_EFI: case GRUB_INSTALL_PLATFORM_IA64_EFI: case GRUB_INSTALL_PLATFORM_ARM_EFI: + case GRUB_INSTALL_PLATFORM_ARM64_EFI: case GRUB_INSTALL_PLATFORM_I386_IEEE1275: case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275: case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275: @@ -771,6 +774,7 @@ main (int argc, char *argv[]) case GRUB_INSTALL_PLATFORM_I386_EFI: case GRUB_INSTALL_PLATFORM_X86_64_EFI: case GRUB_INSTALL_PLATFORM_ARM_EFI: + case GRUB_INSTALL_PLATFORM_ARM64_EFI: case GRUB_INSTALL_PLATFORM_IA64_EFI: case GRUB_INSTALL_PLATFORM_I386_IEEE1275: case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275: @@ -810,6 +814,7 @@ main (int argc, char *argv[]) case GRUB_INSTALL_PLATFORM_I386_EFI: case GRUB_INSTALL_PLATFORM_X86_64_EFI: case GRUB_INSTALL_PLATFORM_ARM_EFI: + case GRUB_INSTALL_PLATFORM_ARM64_EFI: case GRUB_INSTALL_PLATFORM_IA64_EFI: case GRUB_INSTALL_PLATFORM_I386_IEEE1275: case GRUB_INSTALL_PLATFORM_ARM_UBOOT: @@ -857,6 +862,7 @@ main (int argc, char *argv[]) case GRUB_INSTALL_PLATFORM_I386_EFI: case GRUB_INSTALL_PLATFORM_X86_64_EFI: case GRUB_INSTALL_PLATFORM_ARM_EFI: + case GRUB_INSTALL_PLATFORM_ARM64_EFI: case GRUB_INSTALL_PLATFORM_IA64_EFI: is_efi = 1; break; @@ -959,6 +965,10 @@ main (int argc, char *argv[]) efi_suffix = "arm"; efi_suffix_upper = "ARM"; break; + case GRUB_INSTALL_PLATFORM_ARM64_EFI: + efi_suffix = "arm64"; + efi_suffix_upper = "AARCH64"; + break; default: break; } @@ -1227,6 +1237,7 @@ main (int argc, char *argv[]) case GRUB_INSTALL_PLATFORM_I386_EFI: case GRUB_INSTALL_PLATFORM_X86_64_EFI: case GRUB_INSTALL_PLATFORM_ARM_EFI: + case GRUB_INSTALL_PLATFORM_ARM64_EFI: case GRUB_INSTALL_PLATFORM_IA64_EFI: g = grub_util_guess_efi_drive (*curdev); break; @@ -1316,6 +1327,7 @@ main (int argc, char *argv[]) case GRUB_INSTALL_PLATFORM_I386_EFI: case GRUB_INSTALL_PLATFORM_X86_64_EFI: case GRUB_INSTALL_PLATFORM_ARM_EFI: + case GRUB_INSTALL_PLATFORM_ARM64_EFI: case GRUB_INSTALL_PLATFORM_IA64_EFI: core_name = "core.efi"; snprintf (mkimage_target, sizeof (mkimage_target), @@ -1418,6 +1430,7 @@ main (int argc, char *argv[]) } break; case GRUB_INSTALL_PLATFORM_ARM_EFI: + case GRUB_INSTALL_PLATFORM_ARM64_EFI: case GRUB_INSTALL_PLATFORM_IA64_EFI: case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS: case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS: @@ -1567,6 +1580,7 @@ main (int argc, char *argv[]) case GRUB_INSTALL_PLATFORM_X86_64_EFI: case GRUB_INSTALL_PLATFORM_ARM_EFI: + case GRUB_INSTALL_PLATFORM_ARM64_EFI: case GRUB_INSTALL_PLATFORM_IA64_EFI: { char *dst = grub_util_path_concat (2, efidir, efi_file); diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in index 93336075b..5eb58969a 100644 --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in @@ -198,9 +198,11 @@ export GRUB_DEFAULT \ GRUB_HIDDEN_TIMEOUT \ GRUB_HIDDEN_TIMEOUT_QUIET \ GRUB_TIMEOUT \ + GRUB_TIMEOUT_STYLE \ GRUB_DEFAULT_BUTTON \ GRUB_HIDDEN_TIMEOUT_BUTTON \ GRUB_TIMEOUT_BUTTON \ + GRUB_TIMEOUT_STYLE_BUTTON \ GRUB_BUTTON_CMOS_ADDRESS \ GRUB_BUTTON_CMOS_CLEAN \ GRUB_DISTRIBUTOR \ diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c index 4f619b925..5240fe2aa 100644 --- a/util/grub-mkimagexx.c +++ b/util/grub-mkimagexx.c @@ -718,6 +718,35 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections, break; } break; + case EM_AARCH64: + { + sym_addr += addend; + switch (ELF_R_TYPE (info)) + { + case R_AARCH64_ABS64: + { + *target = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr); + } + break; + case R_AARCH64_JUMP26: + case R_AARCH64_CALL26: + { + grub_err_t err; + sym_addr -= offset; + sym_addr -= SUFFIX (entry_point); + err = grub_arm64_reloc_xxxx26((grub_uint32_t *)target, + sym_addr); + if (err) + grub_util_error ("%s", grub_errmsg); + } + break; + default: + grub_util_error (_("relocation %d is not implemented yet"), + (unsigned long long) ELF_R_TYPE (info)); + break; + } + break; + } #endif #if defined(MKIMAGE_ELF32) case EM_ARM: @@ -995,6 +1024,32 @@ SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out, break; } break; + case EM_AARCH64: + switch (ELF_R_TYPE (info)) + { + case R_AARCH64_ABS64: + { + Elf_Addr addr; + + addr = section_address + offset; + current_address + = SUFFIX (add_fixup_entry) (&lst, + GRUB_PE32_REL_BASED_DIR64, + addr, 0, current_address, + image_target); + } + break; + /* Relative relocations do not require fixup entries. */ + case R_AARCH64_CALL26: + case R_AARCH64_JUMP26: + break; + default: + grub_util_error (_("fixup for relocation %d is not implemented yet"), + (unsigned long long) ELF_R_TYPE (info)); + break; + } + break; + break; #if defined(MKIMAGE_ELF32) case EM_ARM: switch (ELF_R_TYPE (info)) @@ -1357,7 +1412,7 @@ SUFFIX (load_image) (const char *kernel_path, size_t *exec_size, image_target); if (*start == 0) grub_util_error ("start symbol is not defined"); - + SUFFIX (entry_point) = (Elf_Addr) *start; /* Resolve addresses in the virtual address space. */ @@ -1366,7 +1421,7 @@ SUFFIX (load_image) (const char *kernel_path, size_t *exec_size, num_sections, strtab, out_img, ia64_toff, ia64_got_off, image_target); - + *reloc_size = SUFFIX (make_reloc_section) (e, reloc_section, section_vaddresses, sections, section_entsize, num_sections, diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in index 5516a4167..7b1555b80 100644 --- a/util/grub.d/00_header.in +++ b/util/grub.d/00_header.in @@ -309,42 +309,69 @@ fi make_timeout () { - if [ "$quick_boot" = 1 ] ; then - cat << EOF -if [ "\${recordfail}" = 1 ]; then + cat << EOF +if [ "\${recordfail}" = 1 ] ; then set timeout=${GRUB_RECORDFAIL_TIMEOUT:--1} -else - set timeout=${2} fi +else EOF - elif [ "x${1}" != "x" ] ; then - if [ "x${GRUB_HIDDEN_TIMEOUT_QUIET}" = "xtrue" ] ; then - verbose= + if [ "x${1}${3}" != "x" ] ; then + if [ "x${3}" != "x" ] ; then + timeout="${2}" + style="${3}" else + # Handle the deprecated GRUB_HIDDEN_TIMEOUT scheme. + timeout="${1}" + if [ "x${2}" != "x0" ] ; then + grub_warn "$(gettext "Setting GRUB_TIMEOUT to a non-zero value when GRUB_HIDDEN_TIMEOUT is set is no longer supported.")" + fi + if [ "x${GRUB_HIDDEN_TIMEOUT_QUIET}" = "xtrue" ] ; then + style="hidden" + else + style="countdown" + fi + fi + if [ "x${style}" = "xcountdown" ] ; then verbose=" --verbose" + else + verbose= fi cat << EOF -if sleep$verbose --interruptible ${1} ; then - set timeout=${2} -fi + if [ x\$feature_timeout_style = xy ] ; then + set timeout_style=${style} + set timeout=${timeout} +EOF + if [ "x${style}" != "xmenu" ] ; then + cat << EOF + # Fallback hidden-timeout code in case the timeout_style feature is + # unavailable. + elif sleep${verbose} --interruptible ${timeout} ; then + set timeout=0 +EOF + fi + cat << EOF + fi EOF else cat << EOF -set timeout=${2} + set timeout=${2} EOF fi + cat << EOF +fi +EOF } if [ "x$GRUB_BUTTON_CMOS_ADDRESS" != "x" ]; then cat < /dev/null`" -o -z "`which linux-boot-prober 2> /dev/null`" ] ; then # missing os-prober and/or linux-boot-prober - adjust_timeout exit 0 fi OSPROBED="`os-prober | tr ' ' '^' | paste -s -d ' '`" if [ -z "${OSPROBED}" ] ; then # empty os-prober output, nothing doing - adjust_timeout exit 0 fi diff --git a/util/mkimage.c b/util/mkimage.c index 55e2c906d..9b482712c 100644 --- a/util/mkimage.c +++ b/util/mkimage.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -578,6 +579,22 @@ static const struct grub_install_image_target_desc image_targets[] = .pe_target = GRUB_PE32_MACHINE_ARMTHUMB_MIXED, .elf_target = EM_ARM, }, + { + .dirname = "arm64-efi", + .names = { "arm64-efi", NULL }, + .voidp_sizeof = 8, + .bigendian = 0, + .id = IMAGE_EFI, + .flags = PLATFORM_FLAGS_NONE, + .total_module_size = TARGET_NO_FIELD, + .decompressor_compressed_size = TARGET_NO_FIELD, + .decompressor_uncompressed_size = TARGET_NO_FIELD, + .decompressor_uncompressed_addr = TARGET_NO_FIELD, + .section_align = GRUB_PE32_SECTION_ALIGNMENT, + .vaddr_offset = EFI64_HEADER_SIZE, + .pe_target = GRUB_PE32_MACHINE_ARM64, + .elf_target = EM_AARCH64, + }, }; #define grub_target_to_host32(x) (grub_target_to_host32_real (image_target, (x)))