Byron Stanoszek
2007-Jan-04 19:17 UTC
[syslinux] Automatically choose between 32-bit and 64-bit kernel
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
H. Peter Anvin
2007-Jan-04 19:33 UTC
[syslinux] Automatically choose between 32-bit and 64-bit kernel
Byron Stanoszek wrote:> 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 >I really don't want to put this kind of stuff in the assembly code. There are arbitrary complex rules one may want to have for kernel selection, and that stuff belongs in a com32 module. -hpa
Erwan Velu
2007-Jan-05 10:59 UTC
[syslinux] Automatically choose between 32-bit and 64-bit kernel
Byron Stanoszek wrote:> 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: >I've been starting some stuff on the hardware detection. Some com32 modules are able to detect the hardware capabilities. The x86_64 capability is one of those. Now we need to define a kind of script language than can help people to defines rules to match some hardware capability and some syslinux configuration.