[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

MENU DEFAULT64 support for syslinux



On Mon, Jun 9, 2008 at 1:08 PM, Frans Pop <elendil@planet.nl> wrote:
> * Installer images for i386 and amd64 have a new boot menu using
>  syslinux's vesamenu. This allows for a more user-friendly selection
>  of for example the regular or graphical installer. For the multi-
>  architecture CD/DVD images this change means the 64-bits version of
>  the installer needs to be selected manually from the menu. See the
>  Installation Guide [2] for details on how to use the new menu.

Beta 2 is looking nice, but not having multi-arch boot detection was a
bummer.  So I took it upon myself to add the missing functionality to
menu.c32/vesamenu.c32.  I'm posting the patch here first because I Am
Not A C Programmer(TM), and I really need more set of eyes on it.
Functionally it seems to be working well, as I converted my own
distro's[0] straight isolinux setup to a vesamenu system[1], and it's
been guessing correctly on everything I've thrown at it so far.

RF

[0] http://www.finnix.org/
[1] http://www.finnix.org/Image:Finnix_dev_boot_menu.png
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 00:48:38.424152595 -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 01:01:58.937589284 -0700
@@ -66,6 +66,28 @@
   NULL
 };
 
+#define cpuid(func,ax,bx,cx,dx)\
+	__asm__ __volatile__ ("cpuid":\
+	"=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) : "a" (func));
+
+/*
+ * Determine if a CPU is x86_64 capable
+ */
+int is_64bit(void) {
+  unsigned int eax,ebx,ecx,edx;
+
+  cpuid(0x80000000,eax,ebx,ecx,edx);
+  /* if 0x80000001 is available, it's an AMD and/or x86_64 CPU */
+  if(eax >= 0x80000001) {
+    cpuid(0x80000001,eax,ebx,ecx,edx);
+    /* Bit 29 of 0x80000001_edx specifies x86_64 */
+    if((edx&(1<<29)) == (1<<29)) {
+      return 1;
+    }
+  }
+  return 0;
+}
+
 /*
  * Search the list of all menus for a specific label
  */
@@ -206,6 +228,7 @@
   unsigned int ipappend;
   unsigned int menuhide;
   unsigned int menudefault;
+  unsigned int menudefault64;
   unsigned int menuseparator;
   unsigned int menudisabled;
   unsigned int menuindent;
@@ -273,6 +296,8 @@
   struct menu_entry *me;
   const struct syslinux_ipappend_strings *ipappend;
 
+  int cpu_is_64bit = is_64bit();
+
   if (!ld->label)
     return;			/* Nothing defined */
 
@@ -361,8 +386,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 && cpu_is_64bit ) {
+      m->defentry = m->nentries-1;
+      m->has_default64 = 1;
+    }
+
   }
 
   clear_label_data(ld);
@@ -620,6 +663,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 +920,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: