From 15a463d7420ecbe58ac595e3411f4cc466b10a9e Mon Sep 17 00:00:00 2001 From: Leif Lindholm Date: Sat, 16 Nov 2013 20:52:55 +0100 Subject: [PATCH 01/24] ARM 64 port by Leif Lindholm --- Makefile.util.def | 12 +- conf/Makefile.common | 3 + configure.ac | 8 ++ gentpl.py | 7 +- grub-core/Makefile.am | 5 + grub-core/Makefile.core.def | 14 ++ grub-core/kern/arm64/cache.c | 72 +++++++++++ grub-core/kern/arm64/cache_flush.S | 67 ++++++++++ grub-core/kern/arm64/dl.c | 199 +++++++++++++++++++++++++++++ grub-core/kern/arm64/dl_helper.c | 70 ++++++++++ grub-core/kern/arm64/efi/startup.S | 34 +++++ grub-core/lib/arm64/setjmp.S | 53 ++++++++ grub-core/lib/efi/halt.c | 2 +- grub-core/lib/setjmp.S | 2 + include/grub/arm64/efi/memory.h | 1 + include/grub/arm64/reloc.h | 24 ++++ include/grub/arm64/setjmp.h | 27 ++++ include/grub/arm64/time.h | 29 +++++ include/grub/arm64/types.h | 34 +++++ include/grub/efi/api.h | 3 +- include/grub/efi/pe32.h | 1 + include/grub/elf.h | 16 +++ include/grub/util/install.h | 1 + util/grub-install.c | 16 +++ util/grub-mkimagexx.c | 59 ++++++++- util/mkimage.c | 17 +++ 26 files changed, 759 insertions(+), 17 deletions(-) create mode 100644 grub-core/kern/arm64/cache.c create mode 100644 grub-core/kern/arm64/cache_flush.S create mode 100644 grub-core/kern/arm64/dl.c create mode 100644 grub-core/kern/arm64/dl_helper.c create mode 100644 grub-core/kern/arm64/efi/startup.S create mode 100644 grub-core/lib/arm64/setjmp.S create mode 100644 include/grub/arm64/efi/memory.h create mode 100644 include/grub/arm64/reloc.h create mode 100644 include/grub/arm64/setjmp.h create mode 100644 include/grub/arm64/time.h create mode 100644 include/grub/arm64/types.h diff --git a/Makefile.util.def b/Makefile.util.def index ede74687e..b17c89bc5 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; @@ -176,8 +178,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; @@ -511,8 +511,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; @@ -557,8 +555,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; @@ -594,8 +590,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; @@ -631,8 +625,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/conf/Makefile.common b/conf/Makefile.common index 39d2f4d60..866998a15 100644 --- a/conf/Makefile.common +++ b/conf/Makefile.common @@ -23,6 +23,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 9f8fb8a35..b7af65c70 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 @@ -1434,6 +1440,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/gentpl.py b/gentpl.py index 3ec853ea0..19fab42e2 100644 --- a/gentpl.py +++ b/gentpl.py @@ -24,7 +24,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 = {} @@ -38,9 +38,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" ] @@ -66,7 +67,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 151b9339a..ec76ca0e1 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 4fff57f16..74aa7470e 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; @@ -750,6 +761,7 @@ module = { enable = mips_arc; enable = ia64_efi; enable = arm_efi; + enable = arm64_efi; enable = arm_uboot; }; @@ -845,6 +857,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; @@ -1707,6 +1720,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..c13ad2163 --- /dev/null +++ b/grub-core/kern/arm64/cache.c @@ -0,0 +1,72 @@ +/* + * 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 + +grub_int64_t grub_arch_cache_dlinesz; +grub_int64_t grub_arch_cache_ilinesz; + +/* Prototypes for asm functions. */ +void grub_arch_sync_caches_real (grub_uint64_t address, grub_uint64_t end); + +static void +probe_caches (void) +{ + grub_uint32_t cache_type; + + /* Read Cache Type Register */ + asm volatile ("mrs %0, ctr_el0": "=r"(cache_type)); + + grub_arch_cache_dlinesz = 8 << ((cache_type >> 16) & 0xf); + grub_arch_cache_ilinesz = 8 << (cache_type & 0xf); + + grub_dprintf("cache", "D$ line size: %lld\n", + (long long) grub_arch_cache_dlinesz); + grub_dprintf("cache", "I$ line size: %lld\n", + (long long) grub_arch_cache_ilinesz); +} + +void +grub_arch_sync_caches (void *address, grub_size_t len) +{ + grub_uint64_t start, end; + + if (grub_arch_cache_dlinesz == 0) + probe_caches(); + if (grub_arch_cache_dlinesz == 0) + grub_fatal ("Unknown cache line size!"); + + grub_dprintf("cache", "syncing caches for %p-%lx\n", + address, (grub_addr_t) address + len); + + /* Align here to both cache lines. Saves a tiny bit of asm complexity and + most of potential problems with different line sizes. */ + start = (grub_uint64_t) address; + end = (grub_uint64_t) address + len; + start = ALIGN_DOWN (start, grub_arch_cache_dlinesz); + start = ALIGN_DOWN (start, grub_arch_cache_ilinesz); + + end = ALIGN_UP (end, grub_arch_cache_dlinesz); + end = ALIGN_UP (end, grub_arch_cache_ilinesz); + + grub_dprintf("cache", "aligned to: %lx-%lx\n", + start, end); + + grub_arch_sync_caches_real (start, end); +} diff --git a/grub-core/kern/arm64/cache_flush.S b/grub-core/kern/arm64/cache_flush.S new file mode 100644 index 000000000..1a35120cf --- /dev/null +++ b/grub-core/kern/arm64/cache_flush.S @@ -0,0 +1,67 @@ +/* + * 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 + */ + +// r0 - *beg (inclusive) +// r1 - *end (exclusive) +clean_dcache_range: + // Clean data cache for range to point-of-unification + ldr x2, =EXT_C(grub_arch_cache_dlinesz) + ldr x2, [x2] +1: cmp x0, x1 + bge 2f + dc cvau, x0 // Clean Virtual Address to PoU + add x0, x0, x2 // Next line + b 1b +2: dsb ish + ret + +// r0 - *beg (inclusive) +// r1 - *end (exclusive) +invalidate_icache_range: + // Invalidate instruction cache for range to point-of-unification + ldr x2, =EXT_C(grub_arch_cache_ilinesz) + ldr x2, [x2] +1: cmp x0, x1 + bge 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 + +// void grub_arch_sync_caches_real (void *address, grub_size_t len) +FUNCTION(grub_arch_sync_caches_real) + dsb ish + stp x0, x30, [sp, #-16]! + stp x0, x1, [sp, #-16]! + bl clean_dcache_range + ldp x0, x1, [sp], #16 + bl invalidate_icache_range + ldp x0, x30, [sp], #16 + 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..b2f7ee591 --- /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..781c2b099 --- /dev/null +++ b/grub-core/kern/arm64/efi/startup.S @@ -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 . + */ + +#include + + .file "startup.S" + .text +FUNCTION(_start) + /* + * EFI_SYSTEM_TABLE and EFI_HANDLE are passed in x1/x0. + */ + ldr x2, =EXT_C(grub_efi_image_handle) + str x0, [x2] + ldr x2, =EXT_C(grub_efi_system_table) + str x1, [x2] + ldr x2, =EXT_C(grub_main) + br x2 + + .end 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/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/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/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 c1cd6b339..0aead0a8a 100644 --- a/include/grub/util/install.h +++ b/include/grub/util/install.h @@ -87,6 +87,7 @@ enum grub_install_plat GRUB_INSTALL_PLATFORM_ARM_EFI, GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS, GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS, + GRUB_INSTALL_PLATFORM_ARM64_EFI, GRUB_INSTALL_PLATFORM_MAX }; diff --git a/util/grub-install.c b/util/grub-install.c index 100f09379..b9b6e6911 100644 --- a/util/grub-install.c +++ b/util/grub-install.c @@ -256,6 +256,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 @@ -389,6 +391,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: @@ -736,6 +739,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: @@ -773,6 +777,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: @@ -818,6 +823,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; @@ -922,6 +928,9 @@ main (int argc, char *argv[]) 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; @@ -946,6 +955,9 @@ main (int argc, char *argv[]) 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; @@ -1171,6 +1183,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; @@ -1258,6 +1271,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), @@ -1358,6 +1372,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: @@ -1488,6 +1503,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-mkimagexx.c b/util/grub-mkimagexx.c index 36a683d6f..b88e9b980 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)) @@ -1358,7 +1413,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. */ @@ -1367,7 +1422,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/mkimage.c b/util/mkimage.c index 4a510228c..4bc82df2f 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))) From d3def58c52337b2b634f9be118d089ee73a6f2a9 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Mon, 18 Nov 2013 17:52:57 +0100 Subject: [PATCH 02/24] Add missing arm64 declaration --- util/grub-install-common.c | 1 + 1 file changed, 1 insertion(+) diff --git a/util/grub-install-common.c b/util/grub-install-common.c index 0bc7ea3ae..1a903a66d 100644 --- a/util/grub-install-common.c +++ b/util/grub-install-common.c @@ -606,6 +606,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" }, }; From 8a07b55a041c3dccbacdf4f6433e46fb124f4099 Mon Sep 17 00:00:00 2001 From: Leif Lindholm Date: Tue, 19 Nov 2013 10:05:23 +0000 Subject: [PATCH 03/24] arm64: cache maintenance code rework + bugfix --- grub-core/kern/arm64/cache.c | 45 ++++++++++++------------------ grub-core/kern/arm64/cache_flush.S | 30 ++++++-------------- 2 files changed, 27 insertions(+), 48 deletions(-) diff --git a/grub-core/kern/arm64/cache.c b/grub-core/kern/arm64/cache.c index c13ad2163..c4f02b868 100644 --- a/grub-core/kern/arm64/cache.c +++ b/grub-core/kern/arm64/cache.c @@ -19,11 +19,14 @@ #include #include -grub_int64_t grub_arch_cache_dlinesz; -grub_int64_t grub_arch_cache_ilinesz; +static grub_int64_t dlinesz; +static grub_int64_t ilinesz; /* Prototypes for asm functions. */ -void grub_arch_sync_caches_real (grub_uint64_t address, grub_uint64_t end); +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) @@ -33,40 +36,28 @@ probe_caches (void) /* Read Cache Type Register */ asm volatile ("mrs %0, ctr_el0": "=r"(cache_type)); - grub_arch_cache_dlinesz = 8 << ((cache_type >> 16) & 0xf); - grub_arch_cache_ilinesz = 8 << (cache_type & 0xf); + dlinesz = 4 << ((cache_type >> 16) & 0xf); + ilinesz = 4 << (cache_type & 0xf); - grub_dprintf("cache", "D$ line size: %lld\n", - (long long) grub_arch_cache_dlinesz); - grub_dprintf("cache", "I$ line size: %lld\n", - (long long) grub_arch_cache_ilinesz); + 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; + grub_uint64_t start, end, max; - if (grub_arch_cache_dlinesz == 0) + if (dlinesz == 0) probe_caches(); - if (grub_arch_cache_dlinesz == 0) + if (dlinesz == 0) grub_fatal ("Unknown cache line size!"); - grub_dprintf("cache", "syncing caches for %p-%lx\n", - address, (grub_addr_t) address + len); + max = dlinesz > ilinesz ? dlinesz : ilinesz; - /* Align here to both cache lines. Saves a tiny bit of asm complexity and - most of potential problems with different line sizes. */ - start = (grub_uint64_t) address; - end = (grub_uint64_t) address + len; - start = ALIGN_DOWN (start, grub_arch_cache_dlinesz); - start = ALIGN_DOWN (start, grub_arch_cache_ilinesz); + start = ALIGN_DOWN ((grub_uint64_t) address, max); + end = ALIGN_UP ((grub_uint64_t) address + len, max); - end = ALIGN_UP (end, grub_arch_cache_dlinesz); - end = ALIGN_UP (end, grub_arch_cache_ilinesz); - - grub_dprintf("cache", "aligned to: %lx-%lx\n", - start, end); - - grub_arch_sync_caches_real (start, end); + 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 index 1a35120cf..589e8eb7a 100644 --- a/grub-core/kern/arm64/cache_flush.S +++ b/grub-core/kern/arm64/cache_flush.S @@ -25,26 +25,25 @@ * Simple cache maintenance functions */ -// r0 - *beg (inclusive) -// r1 - *end (exclusive) -clean_dcache_range: +// x0 - *beg (inclusive) +// x1 - *end (exclusive) +// x2 - line size +FUNCTION(grub_arch_clean_dcache_range) // Clean data cache for range to point-of-unification - ldr x2, =EXT_C(grub_arch_cache_dlinesz) - ldr x2, [x2] 1: cmp x0, x1 bge 2f dc cvau, x0 // Clean Virtual Address to PoU add x0, x0, x2 // Next line b 1b 2: dsb ish + isb ret -// r0 - *beg (inclusive) -// r1 - *end (exclusive) -invalidate_icache_range: +// x0 - *beg (inclusive) +// x1 - *end (exclusive) +// x2 - line size +FUNCTION(grub_arch_invalidate_icache_range) // Invalidate instruction cache for range to point-of-unification - ldr x2, =EXT_C(grub_arch_cache_ilinesz) - ldr x2, [x2] 1: cmp x0, x1 bge 2f ic ivau, x0 // Invalidate Virtual Address to PoU @@ -54,14 +53,3 @@ invalidate_icache_range: 2: dsb ish isb ret - -// void grub_arch_sync_caches_real (void *address, grub_size_t len) -FUNCTION(grub_arch_sync_caches_real) - dsb ish - stp x0, x30, [sp, #-16]! - stp x0, x1, [sp, #-16]! - bl clean_dcache_range - ldp x0, x1, [sp], #16 - bl invalidate_icache_range - ldp x0, x30, [sp], #16 - ret From 1005bed7222fce9f1c8e0dc63e9ae3894ff996c7 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Mon, 25 Nov 2013 13:04:44 +0100 Subject: [PATCH 04/24] Use b.ge form for instructions --- grub-core/kern/arm64/cache.c | 10 +++++----- grub-core/kern/arm64/cache_flush.S | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/grub-core/kern/arm64/cache.c b/grub-core/kern/arm64/cache.c index c4f02b868..b84383da1 100644 --- a/grub-core/kern/arm64/cache.c +++ b/grub-core/kern/arm64/cache.c @@ -31,7 +31,7 @@ void grub_arch_invalidate_icache_range (grub_addr_t beg, grub_addr_t end, static void probe_caches (void) { - grub_uint32_t cache_type; + grub_uint64_t cache_type; /* Read Cache Type Register */ asm volatile ("mrs %0, ctr_el0": "=r"(cache_type)); @@ -46,17 +46,17 @@ probe_caches (void) void grub_arch_sync_caches (void *address, grub_size_t len) { - grub_uint64_t start, end, max; + grub_uint64_t start, end, max_align; if (dlinesz == 0) probe_caches(); if (dlinesz == 0) grub_fatal ("Unknown cache line size!"); - max = dlinesz > ilinesz ? dlinesz : ilinesz; + max_align = dlinesz > ilinesz ? dlinesz : ilinesz; - start = ALIGN_DOWN ((grub_uint64_t) address, max); - end = ALIGN_UP ((grub_uint64_t) address + len, max); + 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 index 589e8eb7a..e064f7ece 100644 --- a/grub-core/kern/arm64/cache_flush.S +++ b/grub-core/kern/arm64/cache_flush.S @@ -31,7 +31,7 @@ FUNCTION(grub_arch_clean_dcache_range) // Clean data cache for range to point-of-unification 1: cmp x0, x1 - bge 2f + b.ge 2f dc cvau, x0 // Clean Virtual Address to PoU add x0, x0, x2 // Next line b 1b @@ -45,7 +45,7 @@ FUNCTION(grub_arch_clean_dcache_range) FUNCTION(grub_arch_invalidate_icache_range) // Invalidate instruction cache for range to point-of-unification 1: cmp x0, x1 - bge 2f + b.ge 2f ic ivau, x0 // Invalidate Virtual Address to PoU add x0, x0, x2 // Next line b 1b From d2f7902af0e5fc2affa5e0b9f38786f116ad8d58 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Mon, 25 Nov 2013 13:06:56 +0100 Subject: [PATCH 05/24] Make arm64 compileable with clang --- grub-core/kern/arm64/efi/startup.S | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/grub-core/kern/arm64/efi/startup.S b/grub-core/kern/arm64/efi/startup.S index 781c2b099..666a7ee3c 100644 --- a/grub-core/kern/arm64/efi/startup.S +++ b/grub-core/kern/arm64/efi/startup.S @@ -24,11 +24,16 @@ FUNCTION(_start) /* * EFI_SYSTEM_TABLE and EFI_HANDLE are passed in x1/x0. */ - ldr x2, =EXT_C(grub_efi_image_handle) + ldr x2, efi_image_handle_val str x0, [x2] - ldr x2, =EXT_C(grub_efi_system_table) + ldr x2, efi_system_table_val str x1, [x2] - ldr x2, =EXT_C(grub_main) + 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) - .end From ebd289335a58e7f27b6bb1e60ee5180eace7290f Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Mon, 25 Nov 2013 13:27:39 +0100 Subject: [PATCH 06/24] Mention clang for arm64 --- INSTALL | 2 ++ 1 file changed, 2 insertions(+) diff --git a/INSTALL b/INSTALL index e81a095e9..751501e9d 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. From 8f236c141916cc149e325fd8ebeab725568bf907 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 28 Nov 2013 02:27:13 +0000 Subject: [PATCH 07/24] Revamp hidden timeout handling 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. --- ChangeLog | 14 ++++ docs/grub.texi | 57 +++++++++++-- grub-core/normal/main.c | 2 +- grub-core/normal/menu.c | 175 ++++++++++++++++++++++++++++++++++----- util/grub-mkconfig.in | 1 + util/grub.d/00_header.in | 43 ++++++++-- 6 files changed, 255 insertions(+), 37 deletions(-) diff --git a/ChangeLog b/ChangeLog index d24f53345..4cc456222 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2013-11-28 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. + 2013-11-27 Vladimir Serbinenko Eliminate variable length arrays in grub_vsnprintf_real. diff --git a/docs/grub.texi b/docs/grub.texi index 6aee292f0..f494a3d9e 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -1298,19 +1298,46 @@ 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. +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_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 according to @samp{GRUB_TIMEOUT}. +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 display the menu. In the @samp{countdown} case, it +will show a one-line indication of the remaining time. + @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. +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. Unset by default. +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_DEFAULT_BUTTON @itemx GRUB_TIMEOUT_BUTTON @@ -3030,6 +3057,7 @@ These variables have special meaning to GRUB. * superusers:: * theme:: * timeout:: +* timeout_style:: @end menu @@ -3462,10 +3490,23 @@ 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. +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} or @samp{GRUB_HIDDEN_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 @section The GRUB environment block diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c index ad3627351..778de61cd 100644 --- a/grub-core/normal/main.c +++ b/grub-core/normal/main.c @@ -523,7 +523,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 9b88290cf..fa85c3533 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,38 @@ 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) + 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 +536,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 +577,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 +586,71 @@ 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_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 +679,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 +785,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/util/grub-mkconfig.in b/util/grub-mkconfig.in index ba1d4ef35..50f73aae5 100644 --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in @@ -186,6 +186,7 @@ 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 \ diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in index 983872035..d5cf34275 100644 --- a/util/grub.d/00_header.in +++ b/util/grub.d/00_header.in @@ -282,14 +282,45 @@ fi make_timeout () { - if [ "x${1}" != "x" ] ; then - if [ "x${GRUB_HIDDEN_TIMEOUT_QUIET}" = "xtrue" ] ; then - verbose= - else - verbose=" --verbose" + if [ "x${GRUB_TIMEOUT_STYLE}" != "x" ] ; then + cat << EOF +if [ x\$feature_timeout_style = xy ] ; then + set timeout_style=${GRUB_TIMEOUT_STYLE} + set timeout=${2} +EOF + if [ "x${GRUB_TIMEOUT_STYLE}" != "xmenu" ] ; then + # Fallback hidden-timeout code in case the timeout_style feature + # is unavailable. Note that we now ignore GRUB_HIDDEN_TIMEOUT + # and take the hidden-timeout from GRUB_TIMEOUT instead. + if [ "x${GRUB_TIMEOUT_STYLE}" = "xhidden" ] ; then + verbose= + else + verbose=" --verbose" + fi + cat << EOF +elif sleep$verbose --interruptible ${2} ; then + set timeout=0 +EOF fi cat << EOF -if sleep$verbose --interruptible ${1} ; then +fi +EOF + elif [ "x${1}" != "x" ] ; then + 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 + verbose= + style="hidden" + else + verbose=" --verbose" + style="countdown" + fi + cat << EOF +if [ x\$feature_timeout_style = xy ] ; then + set timeout_style=$style + set timeout=${1} +elif sleep$verbose --interruptible ${1} ; then set timeout=${2} fi EOF From 827d87e9d6d4d80a87170cca1a6b7396460f4107 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 28 Nov 2013 11:01:53 +0000 Subject: [PATCH 08/24] Fix documentation of timeout expiry. --- docs/grub.texi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/grub.texi b/docs/grub.texi index f494a3d9e..5383aa29a 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -1312,8 +1312,8 @@ displaying the menu, GRUB will wait for the timeout set by will display the menu and wait for input according to @samp{GRUB_TIMEOUT}. 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 display the menu. In the @samp{countdown} case, it -will show a one-line indication of the remaining time. +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_HIDDEN_TIMEOUT Wait this many seconds before displaying the menu. If @key{ESC} is pressed From 8ddf84bfb8df5ae06498c98e336f359628a6c5ef Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 29 Nov 2013 13:48:23 +0000 Subject: [PATCH 09/24] Fix "make -C docs dvi" * 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. --- ChangeLog | 6 ++++++ docs/grub-dev.texi | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 346c01b83..ad8356344 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +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/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. From 471b2683e7da1d6d04fef581ac63424bb57f4eac Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 29 Nov 2013 14:59:25 +0000 Subject: [PATCH 10/24] Move deprecated grub-mkconfig options to a separate table Suggested by Andrey Borzenkov. --- docs/grub.texi | 63 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/docs/grub.texi b/docs/grub.texi index 5383aa29a..f9299041f 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -1315,33 +1315,8 @@ 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_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_DEFAULT_BUTTON @itemx GRUB_TIMEOUT_BUTTON -@itemx GRUB_HIDDEN_TIMEOUT_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}. @@ -1516,6 +1491,44 @@ Each module will be loaded as early as possible, at the start of @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 From 53cc63bf851a057ab5275825dfc1aebffe08302e Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 29 Nov 2013 15:18:05 +0000 Subject: [PATCH 11/24] Add GRUB_TIMEOUT_STYLE_BUTTON support Suggested by Vladimir Serbinenko. --- docs/grub.texi | 21 ++++++++++++--------- util/grub-mkconfig.in | 1 + util/grub.d/00_header.in | 14 +++++++------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/docs/grub.texi b/docs/grub.texi index f9299041f..e730d9191 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -1317,6 +1317,7 @@ case, it will show a one-line indication of the remaining time. @item GRUB_DEFAULT_BUTTON @itemx GRUB_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}. @@ -2517,15 +2518,17 @@ 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 -@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: +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}, +@samp{GRUB_HIDDEN_TIMEOUT_BUTTON} and @samp{GRUB_BUTTON_CMOS_ADDRESS} +variables in default/grub (@pxref{Simple configuration}). +@samp{GRUB_TIMEOUT_BUTTON}, @samp{GRUB_TIMEOUT_STYLE_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: @table @key @item Dell XPS M1330M diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in index 50f73aae5..016ee8259 100644 --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in @@ -190,6 +190,7 @@ export GRUB_DEFAULT \ 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.d/00_header.in b/util/grub.d/00_header.in index d5cf34275..6e8eb8436 100644 --- a/util/grub.d/00_header.in +++ b/util/grub.d/00_header.in @@ -282,17 +282,17 @@ fi make_timeout () { - if [ "x${GRUB_TIMEOUT_STYLE}" != "x" ] ; then + if [ "x${3}" != "x" ] ; then cat << EOF if [ x\$feature_timeout_style = xy ] ; then - set timeout_style=${GRUB_TIMEOUT_STYLE} + set timeout_style=${3} set timeout=${2} EOF - if [ "x${GRUB_TIMEOUT_STYLE}" != "xmenu" ] ; then + if [ "x${3}" != "xmenu" ] ; then # Fallback hidden-timeout code in case the timeout_style feature # is unavailable. Note that we now ignore GRUB_HIDDEN_TIMEOUT # and take the hidden-timeout from GRUB_TIMEOUT instead. - if [ "x${GRUB_TIMEOUT_STYLE}" = "xhidden" ] ; then + if [ "x${3}" = "xhidden" ] ; then verbose= else verbose=" --verbose" @@ -335,12 +335,12 @@ if [ "x$GRUB_BUTTON_CMOS_ADDRESS" != "x" ]; then cat < Date: Fri, 29 Nov 2013 15:25:43 +0000 Subject: [PATCH 12/24] Fix documentation of behaviour after pressing ESC Pointed out by Andrey Borzenkov. --- docs/grub.texi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/grub.texi b/docs/grub.texi index e730d9191..1caee8347 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -1309,11 +1309,11 @@ 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 according to @samp{GRUB_TIMEOUT}. -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. +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 From 095588ef34618232a8696a2cdc2952f3fa4cc8aa Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 29 Nov 2013 15:30:44 +0000 Subject: [PATCH 13/24] Consistently ignore GRUB_TIMEOUT if GRUB_HIDDEN_TIMEOUT is set Pointed out by Vladimir Serbinenko. --- util/grub.d/00_header.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in index 6e8eb8436..84d04999d 100644 --- a/util/grub.d/00_header.in +++ b/util/grub.d/00_header.in @@ -321,7 +321,7 @@ if [ x\$feature_timeout_style = xy ] ; then set timeout_style=$style set timeout=${1} elif sleep$verbose --interruptible ${1} ; then - set timeout=${2} + set timeout=0 fi EOF else From 9b70860ecca300bae6a8997c66352c03c730953c Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 29 Nov 2013 16:11:53 +0000 Subject: [PATCH 14/24] Consolidate timeout generation code a bit. --- util/grub.d/00_header.in | 63 ++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in index 84d04999d..d2e725201 100644 --- a/util/grub.d/00_header.in +++ b/util/grub.d/00_header.in @@ -282,46 +282,41 @@ fi make_timeout () { - if [ "x${3}" != "x" ] ; then - cat << EOF -if [ x\$feature_timeout_style = xy ] ; then - set timeout_style=${3} - set timeout=${2} -EOF - if [ "x${3}" != "xmenu" ] ; then - # Fallback hidden-timeout code in case the timeout_style feature - # is unavailable. Note that we now ignore GRUB_HIDDEN_TIMEOUT - # and take the hidden-timeout from GRUB_TIMEOUT instead. - if [ "x${3}" = "xhidden" ] ; then - verbose= - else - verbose=" --verbose" - fi - cat << EOF -elif sleep$verbose --interruptible ${2} ; then - set timeout=0 -EOF - fi - cat << EOF -fi -EOF - elif [ "x${1}" != "x" ] ; then - 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 - verbose= - style="hidden" + 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" - style="countdown" + else + verbose= fi cat << EOF if [ x\$feature_timeout_style = xy ] ; then - set timeout_style=$style - set timeout=${1} -elif sleep$verbose --interruptible ${1} ; 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 From f70ab525f941fc24cd721720751e2f0ff283b17c Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 29 Nov 2013 17:19:37 +0000 Subject: [PATCH 15/24] Remove a few references to GRUB_HIDDEN_TIMEOUT* Reported by Andrey Borzenkov. --- docs/grub.texi | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/docs/grub.texi b/docs/grub.texi index 1caee8347..fdcd6181d 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -2520,11 +2520,10 @@ menu requires several fancy features of your terminal. 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}, -@samp{GRUB_HIDDEN_TIMEOUT_BUTTON} and @samp{GRUB_BUTTON_CMOS_ADDRESS} -variables in default/grub (@pxref{Simple configuration}). -@samp{GRUB_TIMEOUT_BUTTON}, @samp{GRUB_TIMEOUT_STYLE_BUTTON}, -@samp{GRUB_DEFAULT_BUTTON}, and @samp{GRUB_HIDDEN_TIMEOUT_BUTTON} are used +@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_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 @@ -3510,8 +3509,8 @@ 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} or -@samp{GRUB_HIDDEN_TIMEOUT} (@pxref{Simple configuration}). +This variable is often set by @samp{GRUB_TIMEOUT} (@pxref{Simple +configuration}). @node timeout_style From ce55ed03892f7956a7e9a23766e7b493f89f2c03 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Sat, 30 Nov 2013 11:14:30 +0100 Subject: [PATCH 16/24] Remove leftover GRUB_IA64_DL_TRAMP_SIZE. --- ChangeLog | 4 ++++ grub-core/kern/ia64/dl.c | 3 ++- grub-core/kern/ia64/dl_helper.c | 2 -- include/grub/dl.h | 1 - 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index ad8356344..8aef55ea6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +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 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/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 From 35de6d4bac99973d8ec3ce02e6e82d0e2e2c0dd2 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Sat, 30 Nov 2013 11:19:06 +0100 Subject: [PATCH 17/24] * grub-core/lib/libgcrypt/mpi/longlong.h: Fix compilation error with -march=armv3. --- ChangeLog | 5 +++++ grub-core/lib/libgcrypt/mpi/longlong.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 8aef55ea6..bf0124c11 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +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. 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" \ From d74b9a1d1ac6d2a11440084b2d3396701a755379 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Sat, 30 Nov 2013 11:31:14 +0100 Subject: [PATCH 18/24] Ensure that -mno-unaligned-access or some equivalent option is used. --- ChangeLog | 4 ++++ acinclude.m4 | 20 -------------------- configure.ac | 23 +++++++++++++++++++---- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index bf0124c11..ead7b2620 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +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 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/configure.ac b/configure.ac index 1989f87b7..fe6028cfb 100644 --- a/configure.ac +++ b/configure.ac @@ -839,11 +839,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 From be0d45555ee656cd0d54657851c060871fa9f04b Mon Sep 17 00:00:00 2001 From: Andrey Borzenkov Date: Sat, 30 Nov 2013 14:57:11 +0400 Subject: [PATCH 19/24] document sleep command exit codes --- ChangeLog | 4 ++++ docs/grub.texi | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index ead7b2620..e61197a88 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +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. diff --git a/docs/grub.texi b/docs/grub.texi index 529e328b2..ceea7eb3a 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -4883,7 +4883,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 From 8a952d20d166cba1e2d5d6d08ff67b9486bdbcc9 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Sat, 30 Nov 2013 16:51:35 +0100 Subject: [PATCH 20/24] Missing ChangeLog entry --- ChangeLog | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ChangeLog b/ChangeLog index e61197a88..1e306862b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2013-11-30 Leif Lindholm + + New port arm64-efi. + 2013-11-30 Andrey Borzenkov * docs/grub.texi (sleep): Document exit codes. From 5037aa9a7be2e244c7328fc3737a436ebcf05232 Mon Sep 17 00:00:00 2001 From: Andrey Borzenkov Date: Sat, 30 Nov 2013 22:36:10 +0400 Subject: [PATCH 21/24] fix libgrub.pp build post arm64 merge grub-core/kern/arm64/dl_helper.c:26:28: fatal error: grub/cpu/reloc.h: No such file or directory --- ChangeLog | 5 +++++ grub-core/kern/arm64/dl_helper.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 1e306862b..7b663dbf3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +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. diff --git a/grub-core/kern/arm64/dl_helper.c b/grub-core/kern/arm64/dl_helper.c index b2f7ee591..6f99087e3 100644 --- a/grub-core/kern/arm64/dl_helper.c +++ b/grub-core/kern/arm64/dl_helper.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include static grub_ssize_t sign_compress_offset (grub_ssize_t offset, int bitpos) From 9e4e6ddfbfaad73e0c0f542c818c247135961c48 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Mon, 2 Dec 2013 06:51:13 +0100 Subject: [PATCH 22/24] * util/config.c: Add missing pointer adjustment. Reported by: qwertial --- ChangeLog | 5 +++++ util/config.c | 3 +++ 2 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index 7b663dbf3..c1dad3bd9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +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 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); From f315b508aeda7cf12cdbed7d49ec1a9cbf84a8e3 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 3 Dec 2013 16:11:00 +0000 Subject: [PATCH 23/24] Reduce nesting level. --- grub-core/normal/menu.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c index fa85c3533..b47991aba 100644 --- a/grub-core/normal/menu.c +++ b/grub-core/normal/menu.c @@ -110,10 +110,12 @@ get_timeout_style (void) struct timeout_style_name *style_name; val = grub_env_get ("timeout_style"); - if (val) - for (style_name = timeout_style_names; style_name->name; style_name++) - if (grub_strcmp (style_name->name, val) == 0) - return style_name->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; } From 10955cda069d26a2f879fb766b542251f8bfe8a8 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 3 Dec 2013 16:14:01 +0000 Subject: [PATCH 24/24] Credit and bug reference. --- ChangeLog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog b/ChangeLog index 4cc456222..381188668 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,8 @@ 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-11-27 Vladimir Serbinenko Eliminate variable length arrays in grub_vsnprintf_real.