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 +#include +#include +#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) + +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