On Fri, May 18, 2007 at 08:35:35PM +0200, Yoshinori K. Okuji wrote:
> > This module checks for CPU features 
> > (currently only the long_mode flag, but more could be added if needed)
> > using cpuid.  The idea behind this is that grub.cfg scripts can use it to
> > decide wether a 64-bit or 32-bit Linux image should be boot (e.g. like
> > Debian multiarch CDs do).  I haven't investigated what the syntax for that
> > hack would be, although I assume it's possible.
> 
> Personally, I think it would be cleaner to just return true or false (like 
> test) rather than setting an environment variable. For instance:

Done.

> if cpuid --long-mode; then ...; else ...; fi

The return value ($?) is set, but this syntax doesn't work.  How can this
functionality be tested?

> No. Please use commands/i386/. "util" is strictly for utilities for an host 
> operating system.

Done.

Please have a look at the new patch.

2007-05-19  Robert Millan  <[EMAIL PROTECTED]>

        * commands/i386/cpuid.c: New module.
        * DISTLIST: Add it.
        * conf/i386-efi.rmk: Enable cpuid.mod.
        * conf/i386-pc.rmk: Likewise.

-- 
Robert Millan

My spam trap is [EMAIL PROTECTED]  Note: this address is only intended
for spam harvesters.  Writing to it will get you added to my black list.
diff -Nur grub2-1.95+20070516.old/commands/i386/cpuid.c grub2-1.95+20070516/commands/i386/cpuid.c
--- grub2-1.95+20070516.old/commands/i386/cpuid.c	1970-01-01 01:00:00.000000000 +0100
+++ grub2-1.95+20070516/commands/i386/cpuid.c	2007-05-19 12:49:45.000000000 +0200
@@ -0,0 +1,94 @@
+/* cpuid.c - test for CPU features */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006, 2007  Free Software Foundation, Inc.
+ *  Based on gcc/gcc/config/i386/driver-i386.c
+ *
+ *  This program 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 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/env.h>
+
+#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)
+
+unsigned char has_longmode = 0;
+
+static const struct grub_arg_option options[] =
+  {
+    {"long-mode", 'l', 0, "check for long mode flag (default)", 0, 0},
+    {0, 0, 0, 0, 0, 0}
+  };
+
+static grub_err_t
+grub_cmd_cpuid (struct grub_arg_list *state __attribute__ ((unused)), int argc,
+	       char **args)
+
+{
+  return !has_longmode;
+}
+
+GRUB_MOD_INIT(cpuid)
+{
+#ifdef __x86_64__
+  /* grub-emu */
+  has_longmode = 1;
+#else
+  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)
+    goto done;
+
+  /* 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)
+    goto done;
+
+  cpuid (0x80000000, eax, ebx, ecx, edx);
+  ext_level = eax;
+  if (ext_level < 0x80000000)
+    goto done;
+
+  cpuid (0x80000001, eax, ebx, ecx, edx);
+  has_longmode = !!(edx & bit_LM);
+done:
+#endif
+
+  grub_register_command ("cpuid", grub_cmd_cpuid, GRUB_COMMAND_FLAG_CMDLINE,
+			 "cpuid", "Check for CPU features", options);
+}
+
+GRUB_MOD_FINI(cpuid)
+{
+  grub_unregister_command ("cpuid");
+}
diff -Nur grub2-1.95+20070516.old/conf/i386-efi.rmk grub2-1.95+20070516/conf/i386-efi.rmk
--- grub2-1.95+20070516.old/conf/i386-efi.rmk	2007-05-16 17:05:00.000000000 +0200
+++ grub2-1.95+20070516/conf/i386-efi.rmk	2007-05-19 11:46:29.000000000 +0200
@@ -43,6 +43,7 @@
 	commands/terminal.c commands/ls.c commands/test.c 		\
 	commands/search.c						\
 	commands/i386/pc/halt.c commands/i386/pc/reboot.c		\
+	commands/i386/cpuid.c						\
 	disk/loopback.c							\
 	fs/affs.c fs/ext2.c fs/fat.c fs/fshelp.c fs/hfs.c fs/iso9660.c	\
 	fs/jfs.c fs/minix.c fs/sfs.c fs/ufs.c fs/xfs.c fs/hfsplus.c	\
@@ -71,7 +72,7 @@
 
 # Modules.
 pkgdata_MODULES = kernel.mod normal.mod _chain.mod chain.mod \
-	_linux.mod linux.mod
+	_linux.mod linux.mod cpuid.mod
 
 # For kernel.mod.
 kernel_mod_EXPORTS = no
@@ -130,4 +131,9 @@
 linux_mod_CFLAGS = $(COMMON_CFLAGS)
 linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For cpuid.mod.
+cpuid_mod_SOURCES = commands/i386/cpuid.c
+cpuid_mod_CFLAGS = $(COMMON_CFLAGS)
+cpuid_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 include $(srcdir)/conf/common.mk
diff -Nur grub2-1.95+20070516.old/conf/i386-pc.rmk grub2-1.95+20070516/conf/i386-pc.rmk
--- grub2-1.95+20070516.old/conf/i386-pc.rmk	2007-05-16 17:19:38.000000000 +0200
+++ grub2-1.95+20070516/conf/i386-pc.rmk	2007-05-19 11:46:19.000000000 +0200
@@ -90,6 +90,7 @@
 	commands/terminal.c commands/ls.c commands/test.c 		\
 	commands/search.c commands/blocklist.c				\
 	commands/i386/pc/halt.c commands/i386/pc/reboot.c		\
+	commands/i386/cpuid.c						\
 	disk/loopback.c	disk/raid.c disk/lvm.c				\
 	fs/affs.c fs/ext2.c fs/fat.c fs/fshelp.c fs/hfs.c fs/iso9660.c	\
 	fs/jfs.c fs/minix.c fs/sfs.c fs/ufs.c fs/xfs.c fs/hfsplus.c	\
@@ -120,7 +121,7 @@
 pkgdata_MODULES = _chain.mod _linux.mod linux.mod normal.mod \
 	_multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod	\
 	vbe.mod vbetest.mod vbeinfo.mod video.mod gfxterm.mod \
-	videotest.mod play.mod bitmap.mod tga.mod
+	videotest.mod play.mod bitmap.mod tga.mod cpuid.mod
 
 # For _chain.mod.
 _chain_mod_SOURCES = loader/i386/pc/chainloader.c
@@ -224,4 +225,9 @@
 tga_mod_CFLAGS = $(COMMON_CFLAGS)
 tga_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For cpuid.mod.
+cpuid_mod_SOURCES = commands/i386/cpuid.c
+cpuid_mod_CFLAGS = $(COMMON_CFLAGS)
+cpuid_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 include $(srcdir)/conf/common.mk
diff -Nur grub2-1.95+20070516.old/DISTLIST grub2-1.95+20070516/DISTLIST
--- grub2-1.95+20070516.old/DISTLIST	2007-05-16 17:19:37.000000000 +0200
+++ grub2-1.95+20070516/DISTLIST	2007-05-19 11:45:13.000000000 +0200
@@ -43,6 +43,7 @@
 commands/terminal.c
 commands/test.c
 commands/videotest.c
+commands/i386/cpuid.c
 commands/i386/pc/halt.c
 commands/i386/pc/play.c
 commands/i386/pc/reboot.c
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to