[syslinux] Automatically choose between 32-bit and 64-bit kernel
Byron Stanoszek
gandalf at winds.org
Thu Jan 4 11:17:20 PST 2007
I've been using syslinux on my own Linux recovery CDs for almost a year now,
and in that time I've found it useful to be able to automatically load a
64-bit-capable kernel if the CPU supports it.
I'd like to share my efforts and submit this patch for syslinux-3.31. It adds a
new config file keyword, 'default64', which overrides the default image if a
64-bit CPU is detected. This allows your config file to have something like
this in order to automatically choose between a 32-bit and 64-bit kernel:
default linux
default64 linux64
prompt 0
label linux
kernel vmlinuz
append root=/dev/sr0
label linux64
kernel vmlinuz-64bit
append root=/dev/sr0
Alternatively, this patch can be grabbed from:
http://www.winds.org/pub/linux/syslinux/syslinux-3.31-64bit.patch
It should be 386-safe, but I don't have a 386 to test it out with.
Best regards,
-Byron
diff -ur syslinux-3.31.orig/cpuinit.inc syslinux-3.31/cpuinit.inc
--- syslinux-3.31.orig/cpuinit.inc 2006-09-26 00:52:22.000000000 -0400
+++ syslinux-3.31/cpuinit.inc 2007-01-03 14:41:27.000000000 -0500
@@ -48,12 +48,10 @@
rep movsd
;
-; Check if we're 386 (as opposed to 486+); if so we need to blank out
-; the WBINVD instruction
+; Determine if we're running on a 64-bit CPU
;
-; We check for 486 by setting EFLAGS.AC
+; First, check if we're 386. If so, we need to blank out the WBINVD
instruction
;
-%if DO_WBINVD
pushfd ; Save the good flags
pushfd
pop eax
@@ -69,6 +67,47 @@
;
; 386 - Looks like we better blot out the WBINVD instruction
;
+%if DO_WBINVD
mov byte [try_wbinvd],0c3h ; Near RET
-is_486:
%endif ; DO_WBINVD
+ jmp is_32bit
+is_486:
+;
+; Check if this CPU supports the CPUID command
+;
+ pushfd ; Save the flags again
+ pushfd
+ pop eax
+ mov ebx,eax
+ xor eax,(1 << 21) ; CPUID bit
+ push eax
+ popfd
+ pushfd
+ pop eax
+ popfd ; Restore the original flags
+ xor eax,ebx
+ 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
+;
+ mov eax, 00000000h ; Find last Intel cpuid #
+ cpuid
+ cmp eax, 00000000h
+ je test_amd
+ mov eax, 00000001h ; Read Intel CPU flags
+ cpuid
+ bt edx, 30 ; 64-bit if bit 30 is set
+ jc is_64bit
+
+test_amd: mov eax, 80000000h ; Find last AMD cpuid #
+ cpuid
+ cmp eax, 80000000h
+ jbe is_32bit
+ mov eax, 80000001h ; Read AMD CPU flags
+ cpuid
+ bt edx, 29 ; 64-bit if bit 29 is set
+ jnc is_32bit
+
+is_64bit: mov byte [Is64Bit],1 ; Flag that we're 64-bit
+is_32bit:
diff -ur syslinux-3.31.orig/keywords syslinux-3.31/keywords
--- syslinux-3.31.orig/keywords 2006-09-26 00:52:22.000000000 -0400
+++ syslinux-3.31/keywords 2007-01-03 14:02:22.000000000 -0500
@@ -1,6 +1,7 @@
menu
append
default
+default64
display
font
implicit
diff -ur syslinux-3.31.orig/keywords.inc syslinux-3.31/keywords.inc
--- syslinux-3.31.orig/keywords.inc 2006-09-26 00:52:22.000000000 -0400
+++ syslinux-3.31/keywords.inc 2007-01-03 14:02:38.000000000 -0500
@@ -46,6 +46,7 @@
keyword menu, pc_comment
keyword append, pc_append
keyword default, pc_default
+ keyword default64, pc_default64
keyword display, pc_filecmd, get_msg_file
keyword font, pc_filecmd, loadfont
keyword implicit, pc_setint16, AllowImplicit
diff -ur syslinux-3.31.orig/kwdhash.gen syslinux-3.31/kwdhash.gen
--- syslinux-3.31.orig/kwdhash.gen 2006-09-26 00:52:27.000000000 -0400
+++ syslinux-3.31/kwdhash.gen 2007-01-03 15:17:26.000000000 -0500
@@ -1,6 +1,7 @@
hash_menu equ 0x003719b5
hash_append equ 0xc53999a4
hash_default equ 0xcc5159ed
+hash_default64 equ 0x4567b1c5
hash_display equ 0xd509bc40
hash_font equ 0x0032b1b4
hash_implicit equ 0xa6f50207
diff -ur syslinux-3.31.orig/parseconfig.inc syslinux-3.31/parseconfig.inc
--- syslinux-3.31.orig/parseconfig.inc 2006-09-26 00:52:22.000000000 -0400
+++ syslinux-3.31/parseconfig.inc 2007-01-03 16:34:19.000000000 -0500
@@ -20,7 +20,20 @@
;
; "default" command
;
-pc_default: mov di,default_cmd
+pc_default: cmp byte [HasDefault64],0 ; Check if we accepted
'default64'
+ ja pc_getline ; If so, do nothing
+ mov di,default_cmd
+ call getline
+ mov byte [di-1],0 ; null-terminate
+ ret
+
+;
+; "default64" command
+;
+pc_default64: cmp byte [Is64Bit],0 ; Make sure cpu is 64-bit
+ je pc_getline
+ mov byte [HasDefault64],1 ; Note that we saw a default64
+ mov di,default_cmd
call getline
mov byte [di-1],0 ; null-terminate
ret
@@ -389,6 +402,8 @@
SerialPort dw 0 ; Serial port base (or 0 for no serial
port)
VKernelBytes dw 0 ; Number of bytes used by vkernels
VKernel db 0 ; Have we seen any "label"
statements?
+Is64Bit db 0 ; Is this CPU 64-bit?
+HasDefault64 db 0 ; We've seen a 'default64' statement
section .latebss
alignb 4 ; For the good of REP MOVSD
--
Byron Stanoszek Ph: (330) 644-3059
Systems Programmer Fax: (330) 644-8110
Commercial Timesharing Inc. Email: byron at comtime.com
More information about the Syslinux
mailing list