2007-01-23 Robert Millan * stage2/asm.S (check_64bit): New function. Checks wether 64-bit mode is supported. * grub/asmstub.c (check_64bit): New function (stub). * stage2/shared.h: Declare check_64bit and is64bit. * stage2/common.c: Initialise is64bit with a check_64bit call. * stage2/builtins.c: New builtin (default64). Behaves like default only on 64-bit systems (otherwise it's a no-op). Index: grub/asmstub.c =================================================================== RCS file: /sources/grub/grub/grub/asmstub.c,v retrieving revision 1.86 diff -u -r1.86 asmstub.c --- grub/asmstub.c 23 Apr 2006 10:10:52 -0000 1.86 +++ grub/asmstub.c 23 Jan 2007 21:15:14 -0000 @@ -1309,3 +1309,10 @@ { return 1; } + +int +check_64bit (void) +{ + /* Could be implemented using uname(), but it's useless in the simulator anyway */ + return 0; +} Index: stage2/asm.S =================================================================== RCS file: /sources/grub/grub/stage2/asm.S,v retrieving revision 1.72 diff -u -r1.72 asm.S --- stage2/asm.S 20 Jun 2004 13:48:46 -0000 1.72 +++ stage2/asm.S 23 Jan 2007 21:15:14 -0000 @@ -2365,3 +2365,67 @@ gdtdesc: .word 0x27 /* limit */ .long gdt /* addr */ + +/* + * int check_64bit (void) + * + * Checks wether 64-bit mode is supported + * + * Stolen from a patch originaly intended for syslinux (http://syslinux.zytor.com/archives/2007-January/007832.html) + * Copyright (C) 2007 Byron Stanoszek + * + * Adapted to AT&T syntax by Robert Millan + */ + +ENTRY(check_64bit) + pushl %ebp + pushl %ebx + pushl %edx + + /* Check if this CPU supports the CPUID command */ + pushf + pushf + popl %eax + movl %eax, %ebx + xorl $(1 << 21), %eax // CPUID bit + pushl %eax + popf + pushf + popl %eax + popf // Restore the original flags + xorl %ebx, %eax + jz is_32bit + + /* Now check for the 64-bit flag in the CPU features byte ($0000_0001, edx) + This is bit 30 for Intel CPUs, and bit 29 for AMD CPUs */ + movl $0x00000000, %eax // Find last Intel cpuid # + cpuid + cmpl $0x00000000, %eax + je test_amd + movl $0x00000001, %eax // Read Intel CPU flags + cpuid + btl $30, %edx // 64-bit if bit 30 is set + jc is_64bit + +test_amd: + movl $0x80000000, %eax // Find last AMD cpuid # + cpuid + cmpl $0x80000000, %eax + jbe is_32bit + movl $0x80000001, %eax // Read AMD CPU flags + cpuid + btl $29, %edx // 64-bit if bit 29 is set + jnc is_32bit + +is_64bit: + movl $1, %eax + popl %edx + popl %ebx + popl %ebp + ret +is_32bit: + xorl %eax, %eax + popl %edx + popl %ebx + popl %ebp + ret Index: stage2/builtins.c =================================================================== RCS file: /sources/grub/grub/stage2/builtins.c,v retrieving revision 1.152 diff -u -r1.152 builtins.c --- stage2/builtins.c 21 Mar 2006 20:51:58 -0000 1.152 +++ stage2/builtins.c 23 Jan 2007 21:15:14 -0000 @@ -791,6 +791,23 @@ #endif }; +/* default64 */ +static int +default64_func (char *arg, int flags) +{ + if (is64bit) + return default_func (arg, flags); + else + return 0; +} + +static struct builtin builtin_default64 = +{ + "default64", + default64_func, + BUILTIN_MENU, +}; + #ifdef GRUB_UTIL /* device */ @@ -4807,6 +4824,7 @@ &builtin_configfile, &builtin_debug, &builtin_default, + &builtin_default64, #ifdef GRUB_UTIL &builtin_device, #endif /* GRUB_UTIL */ Index: stage2/common.c =================================================================== RCS file: /sources/grub/grub/stage2/common.c,v retrieving revision 1.27 diff -u -r1.27 common.c --- stage2/common.c 27 Mar 2004 17:02:54 -0000 1.27 +++ stage2/common.c 23 Jan 2007 21:15:14 -0000 @@ -39,6 +39,7 @@ /* This saves the maximum size of extended memory (in KB). */ unsigned long extended_memory; #endif +int is64bit; /* * Error code stuff. @@ -246,6 +247,8 @@ saved_mem_upper = mbi.mem_upper; + is64bit = check_64bit (); + /* Get the drive info. */ /* FIXME: This should be postponed until a Multiboot kernel actually requires it, because this could slow down the start-up Index: stage2/shared.h =================================================================== RCS file: /sources/grub/grub/stage2/shared.h,v retrieving revision 1.100 diff -u -r1.100 shared.h --- stage2/shared.h 2 May 2006 20:46:24 -0000 1.100 +++ stage2/shared.h 23 Jan 2007 21:15:14 -0000 @@ -995,6 +995,9 @@ void init_bios_info (void); +int check_64bit (void); +extern int is64bit; + #endif /* ASM_FILE */ #endif /* ! GRUB_SHARED_HEADER */