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 */