diff --git a/ChangeLog b/ChangeLog index e38ebc5..93c9b00 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2009-07-17 Vladimir Serbinenko + + Always compile efiemu32.o + + * Makefile.in (enable_efiemu): change to ... + (enable_efiemu64): ... this + * commands/i386/cpuid.c (grub_i386_cpuid_has_longmode): new function + * conf/i386-pc.rmk (efiemu_mod_SOURCES): remove efiemu/i386/coredetect.c + (efiemu32.o): always compile this target + * configure.ac: change enable-efiemu to enable-efiemu64. + Restrict efiemu compilation to i386-pc + * efiemu/i386/coredetect.c: remove file + * efiemu/main.c (grub_efiemu_load_file): return error correctly + (grub_efiemu_autocore): fallback to efiemu32.o on amd64 if efiemu64.o + is unavailable + * efiemu/mm.c (grub_efiemu_mmap_init): correct comment style + * include/grub/efiemu/efiemu.h (grub_efiemu_get_default_core_name): + remove + * include/grub/i386/cpuid.h: new file + 2009-07-16 Pavel Roskin * configure.ac: Never add "-c" to CFLAGS. diff --git a/Makefile.in b/Makefile.in index 436db63..f9f0b1a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -108,7 +108,7 @@ enable_lzo = @enable_lzo@ enable_grub_mkfont = @enable_grub_mkfont@ freetype_cflags = @freetype_cflags@ freetype_libs = @freetype_libs@ -enable_efiemu = @enable_efiemu@ +enable_efiemu64 = @enable_efiemu64@ ### General variables. diff --git a/commands/i386/cpuid.c b/commands/i386/cpuid.c index b80b14c..da0429f 100644 --- a/commands/i386/cpuid.c +++ b/commands/i386/cpuid.c @@ -33,6 +33,12 @@ static unsigned char has_longmode = 0; +int +grub_i386_cpuid_has_longmode (void) +{ + return has_longmode; +} + static grub_err_t grub_cmd_cpuid (struct grub_command *cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index f1915b6..899177b 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -209,8 +209,7 @@ efiemu_mod_SOURCES = efiemu/main.c efiemu/i386/loadcore32.c \ efiemu/i386/loadcore64.c efiemu/i386/pc/cfgtables.c \ efiemu/mm.c efiemu/loadcore_common.c efiemu/symbols.c \ efiemu/loadcore32.c efiemu/loadcore64.c \ - efiemu/prepare32.c efiemu/prepare64.c efiemu/pnvram.c \ - efiemu/i386/coredetect.c + efiemu/prepare32.c efiemu/prepare64.c efiemu/pnvram.c efiemu_mod_CFLAGS = $(COMMON_CFLAGS) efiemu_mod_LDFLAGS = $(COMMON_LDFLAGS) @@ -405,8 +404,6 @@ hdparm_mod_SOURCES = commands/hdparm.c lib/hexdump.c hdparm_mod_CFLAGS = $(COMMON_CFLAGS) hdparm_mod_LDFLAGS = $(COMMON_LDFLAGS) -ifeq ($(enable_efiemu), yes) - efiemu32.o: efiemu/runtime/efiemu.c $(TARGET_OBJ2ELF) -rm -f $@ ifeq ($(TARGET_APPLE_CC), 1) @@ -419,6 +416,11 @@ else if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi endif +CLEANFILES += efiemu32.o +pkglib_DATA += efiemu32.o + +ifeq ($(enable_efiemu64), yes) + efiemu64_c.o: efiemu/runtime/efiemu.c ifeq ($(TARGET_APPLE_CC), 1) $(TARGET_CC) -c -m64 -DAPPLE_CC=1 -DELF64 -o $@ -Wall -Werror $< -nostdlib -mno-red-zone -O2 -I$(srcdir)/efiemu/runtime -I$(srcdir)/include -Iinclude @@ -446,8 +448,8 @@ else if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi endif -CLEANFILES += efiemu32.o efiemu64.o efiemu64_c.o efiemu64_s.o -pkglib_DATA += efiemu32.o efiemu64.o +CLEANFILES += efiemu64.o efiemu64_c.o efiemu64_s.o +pkglib_DATA += efiemu64.o endif diff --git a/configure.ac b/configure.ac index 9046403..236f362 100644 --- a/configure.ac +++ b/configure.ac @@ -434,33 +434,34 @@ AH_BOTTOM([#if defined(__i386__) && !defined(GRUB_UTIL) #define NESTED_FUNC_ATTR #endif]) -AC_ARG_ENABLE([efiemu], - [AS_HELP_STRING([--enable-efiemu], - [build and install the efiemu runtimes (default=guessed)])]) -if test x"$enable_efiemu" = xno ; then - efiemu_excuse="explicitly disabled" -fi -if test x"$efiemu_excuse" = x ; then - AC_CACHE_CHECK([whether options required for efiemu work], grub_cv_cc_efiemu, [ +if test "$target_cpu"-"$platform" = i386-pc; then +AC_ARG_ENABLE([efiemu64], + [AS_HELP_STRING([--enable-efiemu64], + [build and install the 64-bit efiemu runtime (default=guessed)])]) +if test x"$enable_efiemu64" = xno ; then + efiemu64_excuse="explicitly disabled" +fi +if test x"$efiemu64_excuse" = x ; then + AC_CACHE_CHECK([whether options required for 64-bit efiemu work], grub_cv_cc_efiemu64, [ CFLAGS="$CFLAGS -m64 -mcmodel=large -mno-red-zone -nostdlib" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], - [grub_cv_cc_efiemu=yes], - [grub_cv_cc_efiemu=no]) + [grub_cv_cc_efiemu64=yes], + [grub_cv_cc_efiemu64=no]) ]) - if test x$grub_cv_cc_efiemu = xno; then - efiemu_excuse="compiler doesn't support compiling with -m64 -mcmodel=large -mno-red-zone -nostdlib" + if test x$grub_cv_cc_efiemu64 = xno; then + efiemu64_excuse="compiler doesn't support compiling with -m64 -mcmodel=large -mno-red-zone -nostdlib" fi fi -if test x"$enable_efiemu" = xyes && test x"$efiemu_excuse" != x ; then - AC_MSG_ERROR([efiemu runtime was explicitly requested but can't be compiled]) +if test x"$enable_efiemu64" = xyes && test x"$efiemu64_excuse" != x ; then + AC_MSG_ERROR([64-bit efiemu runtime was explicitly requested but can't be compiled]) fi -if test x"$efiemu_excuse" = x ; then -enable_efiemu=yes +if test x"$efiemu64_excuse" = x ; then +enable_efiemu64=yes else -enable_efiemu=no +enable_efiemu64=no +fi +AC_SUBST([enable_efiemu64]) fi -AC_SUBST([enable_efiemu]) - # Restore the flags. CC="$tmp_CC" @@ -636,10 +637,12 @@ echo grub-pe2elf will be built but not installed else echo grub-pe2elf will not be built fi -if [ x"$efiemu_excuse" = x ]; then -echo efiemu runtime: Yes +if test "$target_cpu"-"$platform" = i386-pc; then +if [ x"$efiemu64_excuse" = x ]; then +echo efiemu64 runtime: Yes else -echo efiemu runtime: No "($efiemu_excuse)" +echo efiemu64 runtime: No "($efiemu64_excuse)" +fi fi if [ x"$grub_fstest_excuse" = x ]; then echo grub-fstest: Yes diff --git a/efiemu/i386/coredetect.c b/efiemu/i386/coredetect.c deleted file mode 100644 index 828508d..0000000 --- a/efiemu/i386/coredetect.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2009 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#include -#include -#include - -#define cpuid(num,a,b,c,d) \ - asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \ - : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ - : "0" (num)) - -#define bit_LM (1 << 29) - -char * -grub_efiemu_get_default_core_name (void) -{ - - unsigned int eax, ebx, ecx, edx; - unsigned int max_level; - unsigned int ext_level; - - /* See if we can use cpuid. */ - asm volatile ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;" - "pushl %0; popfl; pushfl; popl %0; popfl" - : "=&r" (eax), "=&r" (ebx) - : "i" (0x00200000)); - if (((eax ^ ebx) & 0x00200000) == 0) - return "efiemu32.o"; - - /* Check the highest input value for eax. */ - cpuid (0, eax, ebx, ecx, edx); - /* We only look at the first four characters. */ - max_level = eax; - if (max_level == 0) - return "efiemu32.o"; - - cpuid (0x80000000, eax, ebx, ecx, edx); - ext_level = eax; - if (ext_level < 0x80000000) - return "efiemu32.o"; - - cpuid (0x80000001, eax, ebx, ecx, edx); - return (edx & bit_LM) ? "efiemu64.o" : "efiemu32.o"; -} diff --git a/efiemu/main.c b/efiemu/main.c index b5608e6..ade75d3 100644 --- a/efiemu/main.c +++ b/efiemu/main.c @@ -31,6 +31,7 @@ #include #include #include +#include /* System table. Two version depending on mode */ grub_efi_system_table32_t *grub_efiemu_system_table32 = 0; @@ -204,7 +205,7 @@ grub_efiemu_load_file (const char *filename) file = grub_file_open (filename); if (! file) - return 0; + return grub_errno; err = grub_efiemu_mm_init (); if (err) @@ -237,8 +238,8 @@ grub_efiemu_autocore (void) { const char *prefix; char *filename; - char *suffix; grub_err_t err; + int longmode; if (grub_efiemu_sizeof_uintn_t () != 0) return GRUB_ERR_NONE; @@ -250,17 +251,28 @@ grub_efiemu_autocore (void) "couldn't find efiemu core because prefix " "isn't set"); - suffix = grub_efiemu_get_default_core_name (); + longmode = grub_i386_cpuid_has_longmode (); - filename = grub_malloc (grub_strlen (prefix) + grub_strlen (suffix) + 2); + filename = grub_malloc (grub_strlen (prefix) + sizeof ("/efiemuXX.o")); if (! filename) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't allocate temporary space"); - grub_sprintf (filename, "%s/%s", prefix, suffix); + if (longmode) + { + grub_sprintf (filename, "%s/efiemu64.o", prefix); + err = grub_efiemu_load_file (filename); + } + + if (! longmode || err) + { + grub_errno = GRUB_ERR_NONE; + grub_sprintf (filename, "%s/efiemu32.o", prefix); + err = grub_efiemu_load_file (filename); + } - err = grub_efiemu_load_file (filename); grub_free (filename); + if (err) return err; #ifndef GRUB_UTIL diff --git a/efiemu/mm.c b/efiemu/mm.c index 8b03229..d2666b8 100644 --- a/efiemu/mm.c +++ b/efiemu/mm.c @@ -278,7 +278,7 @@ grub_efiemu_mmap_init (void) return 0; } - // the place for memory used by efiemu itself + /* The place for memory used by efiemu itself. */ mmap_reserved_size = GRUB_EFI_MAX_MEMORY_TYPE + 1; #ifndef GRUB_UTIL diff --git a/include/grub/efiemu/efiemu.h b/include/grub/efiemu/efiemu.h index 20163dd..e3264bb 100644 --- a/include/grub/efiemu/efiemu.h +++ b/include/grub/efiemu/efiemu.h @@ -270,7 +270,6 @@ grub_err_t grub_efiemu_write_value (void * addr, grub_uint32_t value, int minus_handle, int ptv_needed, int size); grub_err_t grub_efiemu_pnvram (void); grub_err_t grub_efiemu_prepare (void); -char *grub_efiemu_get_default_core_name (void); void grub_efiemu_pnvram_cmd_unregister (void); grub_err_t grub_efiemu_autocore (void); #endif /* ! GRUB_EFI_EMU_HEADER */ diff --git a/include/grub/i386/cpuid.h b/include/grub/i386/cpuid.h new file mode 100644 index 0000000..8550afd --- /dev/null +++ b/include/grub/i386/cpuid.h @@ -0,0 +1,6 @@ +#ifndef GRUB_CPUID_CPU_HEADER +#define GRUB_CPUID_CPU_HEADER 1 + +int grub_i386_cpuid_has_longmode (void); + +#endif