Package: syslinux Version: 2:3.63+dfsg-1 Severity: wishlist Tags: patch Current Debian syslinux packages have the patch to add DEFAULT64 support to the core syslinux/isolinux/etc bootloader. However, debian-installer recently switched[0] to the vesamenu.c32 system, which is a chained bootloader on top of syslinux, and cannot take advantage of DEFAULT64.
Attached is a patch that adds "MENU DEFAULT64" support to the menu.c32/vesamenu.c32 chain loader. The classic behavior is of this loader is to highlight a menu entry that contains the "MENU DEFAULT" keyword. This patch extends that functionality to highlight a menu entry that has the "MENU DEFAULT64" keyword if the CPU is x86_64 (but will still fall back to the "MENU DEFAULT" entry if the CPU is not x86_64). An example screenshot of a menu taking advantage of this is here[1]. "Boot Finnix (AMD64)" was highlighted because it was booted on a Core 2 Duo, but on a 32-bit CPU, "Boot Finnix (x86)" would be highlighted by default. [0] http://lists.debian.org/debian-devel-announce/2008/06/msg00002.html [1] http://www.finnix.org/Image:Finnix_dev_boot_menu.png -- System Information: Debian Release: 4.0 APT prefers stable APT policy: (500, 'stable') Architecture: i386 (i686) Shell: /bin/sh linked to /bin/bash Kernel: Linux 2.6.18-5-686 Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
diff -ruN syslinux-3.63+dfsg-orig/com32/menu/menu.h syslinux-3.63+dfsg/com32/menu/menu.h --- syslinux-3.63+dfsg-orig/com32/menu/menu.h 2008-04-10 10:30:35.000000000 -0700 +++ syslinux-3.63+dfsg/com32/menu/menu.h 2008-06-10 09:42:31.749682563 -0700 @@ -163,6 +163,8 @@ struct color_table *color_table; struct fkey_help fkeyhelp[12]; + + int has_default64; }; extern struct menu *root_menu, *start_menu, *hide_menu, *menu_list; diff -ruN syslinux-3.63+dfsg-orig/com32/menu/readconfig.c syslinux-3.63+dfsg/com32/menu/readconfig.c --- syslinux-3.63+dfsg-orig/com32/menu/readconfig.c 2008-04-10 10:30:35.000000000 -0700 +++ syslinux-3.63+dfsg/com32/menu/readconfig.c 2008-06-10 09:48:06.133719250 -0700 @@ -67,6 +67,56 @@ }; /* + * Test for long mode using cpuid instruction + * Based on plugins/cpuid/cpuid.c from win32-loader + * Copyright (C) 2007 Robert Millan <[EMAIL PROTECTED]> + * Based on gcc/gcc/config/i386/driver-i386.c + * Copyright (C) 2006, 2007 Free Software Foundation, Inc. + */ + +#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) + +int +check_64bit () +{ + unsigned int eax, ebx, ecx, edx; + unsigned int max_level; + unsigned int ext_level; + unsigned char has_longmode = 0; + + /* 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: + return has_longmode; +} + +/* * Search the list of all menus for a specific label */ static struct menu * @@ -206,6 +256,7 @@ unsigned int ipappend; unsigned int menuhide; unsigned int menudefault; + unsigned int menudefault64; unsigned int menuseparator; unsigned int menudisabled; unsigned int menuindent; @@ -273,6 +324,8 @@ struct menu_entry *me; const struct syslinux_ipappend_strings *ipappend; + int is_64bit = check_64bit(); + if (!ld->label) return; /* Nothing defined */ @@ -361,8 +414,26 @@ break; } - if ( ld->menudefault && me->action == MA_CMD ) + /* If this ld has DEFAULT on it, it's a candidate for the default entry. + * But if a 64-bit default has already been set, we know that A) the CPU + * is 64-bit, and B) a DEFAULT64 has already occurred, so we don't even + * want to attempt 32-bit defaults anymore. If it's a 64-bit CPU, + * regular DEFAULTs can of course be considered for the default, + * but any past or future DEFAULT64 (with a corresponding 64-bit CPU) + * will eventually win. + */ + if ( ld->menudefault && me->action == MA_CMD && !m->has_default64 ) + m->defentry = m->nentries-1; + + /* If the CPU is 64-bit and DEFAULT64 is set for this ld, set it as + * default. However, if DEFAULT64 is set and the CPU is NOT 64-bit, + * don't even consider it for a default. + */ + if ( ld->menudefault64 && me->action == MA_CMD && is_64bit ) { m->defentry = m->nentries-1; + m->has_default64 = 1; + } + } clear_label_data(ld); @@ -620,6 +691,8 @@ } } else if ( looking_at(p, "default") ) { ld.menudefault = 1; + } else if ( looking_at(p, "default64") ) { + ld.menudefault64 = 1; } else if ( looking_at(p, "hide") ) { ld.menuhide = 1; } else if ( looking_at(p, "passwd") ) { @@ -875,6 +948,7 @@ ld.ipappend = ipappend; ld.menudefault = ld.menuhide = ld.menuseparator = ld.menudisabled = ld.menuindent = 0; + ld.menudefault64 = 0; } else if ( (ep = is_kernel_type(p, &type)) ) { if ( ld.label ) { refstr_put(ld.kernel);