Here's a patch to implement cpuid.mod.  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.

Cpuid detection code has been borrowed from gcc and is FSF-copyrighted.

I'm not sure where would the file go.  I noticed that other utility modules
(e.g. hello/hello.c) add themselves in the top dir, so I suppose i386/cpuid.c
would be ok?

Or perhaps we could have an "util" dir for modules?

-- 
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.
2007-05-18  Robert Millan  <[EMAIL PROTECTED]>

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

diff -x i386-efi.mk -x i386-pc.mk -Nur grub2-1.95+20070515.old/conf/i386-efi.rmk grub2-1.95+20070515/conf/i386-efi.rmk
--- grub2-1.95+20070515.old/conf/i386-efi.rmk	2007-05-18 13:07:26.000000000 +0200
+++ grub2-1.95+20070515/conf/i386-efi.rmk	2007-05-18 13:44:49.000000000 +0200
@@ -70,7 +70,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
@@ -129,4 +129,9 @@
 linux_mod_CFLAGS = $(COMMON_CFLAGS)
 linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For cpuid.mod.
+cpuid_mod_SOURCES = i386/cpuid.c
+cpuid_mod_CFLAGS = $(COMMON_CFLAGS)
+cpuid_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 include $(srcdir)/conf/common.mk
diff -x i386-efi.mk -x i386-pc.mk -Nur grub2-1.95+20070515.old/conf/i386-pc.rmk grub2-1.95+20070515/conf/i386-pc.rmk
--- grub2-1.95+20070515.old/conf/i386-pc.rmk	2007-05-05 01:00:56.000000000 +0200
+++ grub2-1.95+20070515/conf/i386-pc.rmk	2007-05-18 13:41:07.000000000 +0200
@@ -120,7 +120,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 +224,9 @@
 tga_mod_CFLAGS = $(COMMON_CFLAGS)
 tga_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For cpuid.mod.
+cpuid_mod_SOURCES = i386/cpuid.c
+cpuid_mod_CFLAGS = $(COMMON_CFLAGS)
+cpuid_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 include $(srcdir)/conf/common.mk
diff -x i386-efi.mk -x i386-pc.mk -Nur grub2-1.95+20070515.old/DISTLIST grub2-1.95+20070515/DISTLIST
--- grub2-1.95+20070515.old/DISTLIST	2007-05-04 09:11:44.000000000 +0200
+++ grub2-1.95+20070515/DISTLIST	2007-05-18 13:37:05.000000000 +0200
@@ -81,6 +81,7 @@
 fs/xfs.c
 fs/hfsplus.c
 hello/hello.c
+i386/cpuid.c
 include/grub/acorn_filecore.h
 include/grub/arg.h
 include/grub/bitmap.h
diff -x i386-efi.mk -x i386-pc.mk -Nur grub2-1.95+20070515.old/i386/cpuid.c grub2-1.95+20070515/i386/cpuid.c
--- grub2-1.95+20070515.old/i386/cpuid.c	1970-01-01 01:00:00.000000000 +0100
+++ grub2-1.95+20070515/i386/cpuid.c	2007-05-18 13:33:35.000000000 +0200
@@ -0,0 +1,73 @@
+/* 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/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/normal.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)
+
+GRUB_MOD_INIT(cpuid)
+{
+  unsigned int eax, ebx, ecx, edx;
+  unsigned int max_level;
+  unsigned int ext_level;
+  unsigned char has_longmode = 0;
+
+  /* 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:
+  grub_env_set ("cpuid_long_mode", has_longmode ? "1" : "0");
+}
+
+GRUB_MOD_FINI(cpuid)
+{
+  grub_env_unset ("cpuid_long_mode");
+}
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to