Bug#485656: menu.c32/vesamenu.c32: Add MENU DEFAULT64 support
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 <rmh@aybabtu.com>
+ * 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);
Reply to: