diff --git a/ChangeLog b/ChangeLog index 1858a9c..b279f2f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2009-07-17 Vladimir Serbinenko + + Fall back to efiemu32.o if efiemu64.o isn't available. + + * conf/i386-pc.rmk (efiemu_mod_SOURCES): + Remove efiemu/i386/coredetect.c. + * efiemu/i386/coredetect.c: Remove- + * 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-08-28 Colin Watson * term/i386/pc/console.c (bios_data_area): Cast diff --git a/commands/i386/cpuid.c b/commands/i386/cpuid.c index 71f33ef..662c943 100644 --- a/commands/i386/cpuid.c +++ b/commands/i386/cpuid.c @@ -24,6 +24,7 @@ #include #include #include +#include #define cpuid(num,a,b,c,d) \ asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \ @@ -40,6 +41,12 @@ static const struct grub_arg_option options[] = static unsigned char has_longmode = 0; +int +grub_i386_cpuid_has_longmode (void) +{ + return has_longmode; +} + static grub_err_t grub_cmd_cpuid (grub_extcmd_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index 8d7d9fc..86bdeb6 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -204,8 +204,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) 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..b16f4c1 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; + grub_err_t err = GRUB_ERR_NONE; + 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 */