[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