From 17f65ab8e2e8b44b7277ff0238d668d734cbc760 Mon Sep 17 00:00:00 2001 From: Steve McIntyre <93sam@debian.org> Date: Mon, 10 Dec 2012 01:12:44 +0000 Subject: [PATCH] Provide a better set of boot menus when booting via EFI. Previously had a limited set of hard-coded menu entries - this was buggy and didn't take into account all the possible boot variations. Now parse the isolinux menus already provided in the d-i build and generate equivalent grub menus, complete with themes for a reasonable layout with graphics and titles. --- data/wheezy/grub-theme.in | 87 ++++++++++++++ debian/changelog | 5 +- tools/boot/wheezy/boot-x86 | 29 +---- tools/boot/wheezy/parse_isolinux | 194 +++++++++++++++++++++++++++++++ 4 files changed, 290 insertions(+), 25 deletions(-) create mode 100644 data/wheezy/grub-theme.in create mode 100755 tools/boot/wheezy/parse_isolinux diff --git a/data/wheezy/grub-theme.in b/data/wheezy/grub-theme.in new file mode 100644 index 00000000..bf71b067 --- /dev/null +++ b/data/wheezy/grub-theme.in @@ -0,0 +1,87 @@ +title-color: "white" +title-text: TITLE +title-font: "Sans Regular 16" +desktop-color: "black" +desktop-image: "/isolinux/splash.png" +message-color: "white" +message-bg-color: "black" +terminal-font: "Sans Regular 12" + ++ vbox { + top = 80 + left = 45% + width = 60% + height = 100 +#ifdef MENU0 + + hbox { + left = 0 + + label {text = MENU0 font = "Sans 10" color = "#d3d3d3" align = "left"} + } +#endif +#ifdef MENU1 + + hbox { + left = 0 + + label {text = " >" font = "Sans 10" color = "white" align = "left"} + + label {text = MENU1 font = "Sans 10" color = "#d3d3d3" align = "left"} + } +#endif +#ifdef MENU2 + + hbox { + left = 0 + + label {text = " >" font = "Sans 10" color = "white" align = "left"} + + label {text = MENU2 font = "Sans 10" color = "#d3d3d3" align = "left"} + } +#endif +#ifdef MENU3 + + hbox { + left = 0 + + label {text = " >" font = "Sans 10" color = "white" align = "left"} + + label {text = MENU3 font = "Sans 10" color = "#d3d3d3" align = "left"} + } +#endif +#ifdef MENU4 + + hbox { + left = 0 + + label {text = " >" font = "Sans 10" color = "white" align = "left"} + + label {text = MENU4 font = "Sans 10" color = "#d3d3d3" align = "left"} + } +#endif +} + ++ boot_menu { + left = 18% + width = 50% + top = 200 + height = 200 + item_font = "Sans Regular 12" + item_color = #d3d3d3 + selected_item_color = "white" + item_height = 20 + item_padding = 15 + item_spacing = 5 +} + ++ vbox { + top = 100%-60 + left = 10% + + hbox { + top = 0 + left = 20% + + label {text = "Enter: " font = "Sans 10" color = "white" align = "left"} + + label {text = "Select " font = "Sans 10" color = "#d3d3d3" align = "left"} +#ifdef MENU1 + + label {text = " " font = "Sans 10" color = "white" align = "left"} + + label {text = "Esc: " font = "Sans 10" color = "white" align = "left"} + + label {text = "Back up one level " font = "Sans 10" color = "#d3d3d3" align = "left"} +#endif + } + + hbox { + top = 0 + left = 20% + + label {text = "E: " font = "Sans 10" color = "white" align = "left"} + + label {text = "Edit Selection " font = "Sans 10" color = "#d3d3d3" align = "left"} + + label {text = " " font = "Sans 10" color = "white" align = "left"} + + label {text = "C: " font = "Sans 10" color = "white" align = "left"} + + label {text = "GRUB Command line" font = "Sans 10" color = "#d3d3d3" align = "left"} + } +} diff --git a/debian/changelog b/debian/changelog index a156fc21..f8bdb6ad 100644 --- a/debian/changelog +++ b/debian/changelog @@ -7,8 +7,9 @@ debian-cd (3.1.11) UNRELEASED; urgency=low - pull grub EFI pieces out of the latest debian-cd_info.tar.gz blobs in d-i, if they're there. If so, use them to make x86 images bootable via EFI (both via CD and USB) - - generate boot entries for grub on the fly; temporary code for now, - will switch to parsing the isolinux entries shortly instead. + - parse the isolinux menus already provided in the d-i build and + generate equivalent grub menus, complete with themes for a + reasonable layout with graphics and titles. - depending more and more on xorriso rather than genisoimage... * Add version-tracking into dependency sorting. Closes: #687949) + Use/parse output from a newer version of apt so that "apt-cache diff --git a/tools/boot/wheezy/boot-x86 b/tools/boot/wheezy/boot-x86 index d84ffd3d..6943b601 100644 --- a/tools/boot/wheezy/boot-x86 +++ b/tools/boot/wheezy/boot-x86 @@ -394,7 +394,7 @@ add_grub_entry () { PAD=" " echo "menuentry \"${PAD}${DESC}\" {" >> $FILE - echo " set gfxpayload=keep" >> $FILE + echo " set background_color=black" >> $FILE echo " linux /$INSTALLDIR/vmlinuz ${OPTS} --" >> $FILE if [ $GFX = 1 ] ; then echo " initrd /$INSTALLDIR/gtk/initrd.gz" >> $FILE @@ -414,28 +414,11 @@ if [ -d boot$N/isolinux/grub ] ; then mv boot$N/isolinux/grub/* $CDDIR/boot/grub/ rmdir boot$N/isolinux/grub - # TODO: grab pre-made grub entries from the d-i build - if [ $ARCH = amd64 ] ; then - add_grub_entry $CDDIR/boot/grub/grub.cfg \ - "Debian 7.0 graphical installer (64-bit, EFI)" \ - "pci=nocrs verbose" 1 - add_grub_entry $CDDIR/boot/grub/grub.cfg \ - "Debian 7.0 text-mode installer (64-bit, EFI)" \ - "pci=nocrs verbose" 0 - add_grub_entry $CDDIR/boot/grub/grub.cfg \ - "Debian 7.0 text-mode rescue (64-bit, EFI)" \ - "pci=nocrs verbose rescue/enable=true" 0 - else - add_grub_entry $CDDIR/boot/grub/grub.cfg \ - "Debian 7.0 graphical installer (32-bit, EFI)" \ - "pci=nocrs verbose" 1 - add_grub_entry $CDDIR/boot/grub/grub.cfg \ - "Debian 7.0 text-mode installer (32-bit, EFI)" \ - "pci=nocrs verbose" 0 - add_grub_entry $CDDIR/boot/grub/grub.cfg \ - "Debian 7.0 text-mode rescue (32-bit, EFI)" \ - "pci=nocrs verbose rescue/enable=true" 0 - fi + # Create grub menu entries to match the isolinux ones + sed -i '/^menuentry/Q' $CDDIR/boot/grub/grub.cfg; + $BASEDIR/tools/boot/$DI_CODENAME/parse_isolinux \ + boot$N/isolinux $CDDIR $BASEDIR/data/$DI_CODENAME/grub-theme.in "Debian GNU/Linux $DEBVERSION" \ + >> $CDDIR/boot/grub/grub.cfg # Stuff the EFI boot files into a FAT filesystem, making it as # small as possible. 24KiB headroom seems to be enough; diff --git a/tools/boot/wheezy/parse_isolinux b/tools/boot/wheezy/parse_isolinux new file mode 100755 index 00000000..0be8477b --- /dev/null +++ b/tools/boot/wheezy/parse_isolinux @@ -0,0 +1,194 @@ +#!/usr/bin/perl -w +# +# Helper script for debian-cd EFI CD creation +# +# Parse the Isolinux boot menus and create matching grub menus and submenus +# +# Complicated by the way grub theming works - we need to create a +# separate grub theme per submenu simply so that we can describe the +# current (sub)menu appropriately. + +use strict; +use File::Path qw(make_path); + +my $isolinuxdir = shift or die "Need to know where the isolinux directory is!\n"; +my $outdir = shift or die "Need to know where to write output!\n"; +my $grub_theme = shift or die "Need input file location for base grub theme!\n"; +my $tl_desc = shift or die "Need a top-level description (e.g. Debian GNU/Linux 7.0)\n"; +my $theme_dir = "$outdir/boot/grub/theme"; +my @cpp_and_opts = ('cpp', + '-traditional', + '-undef', + '-P', + '-C', + '-Wall', + '-nostdinc'); + +my @lines; +my @menus; +my $incdepth = 0; +my @menu_number = (1,0,0,0,0); +my @menu_title = ('', '', '', '', ''); +my $menudepth = 0; +my $gap = ""; +my %menu; + +sub parse_file { + my $file = shift; + + $incdepth++; +# for(my $i = 0; $i < $incdepth ; $i++) { +# print STDERR " "; +# } +# print STDERR "parsing $isolinuxdir/$file\n"; + open(my $fh, "< $isolinuxdir/$file") or return; + while (my $line = <$fh>) { + chomp $line; + if ($line =~ /^\s*include\ (.*\.cfg)/) { + parse_file($1); + } else { + push(@lines, $line); + } + } + close $fh; + $incdepth--; +} + +sub print_indent { + my $text = shift; + my $i = 1; + while ($i++ < $menudepth) { + print " "; + } + print $text; +} + +sub print_kernel { + my $t = shift; + my %k = %{$t}; + my $initrd; + + # Only print 64-bit kernels + if ($k{"kernel"} =~ /amd/) { + $k{"label"} =~ s/\^//; + if ($k{"append"} =~ s? (initrd=\S+)??) { + $initrd = $1; + $initrd =~ s?^.*initrd=??; + } + print_indent "menuentry '$gap" . $k{"label"} . "' {\n"; + print_indent " set background_color=black\n"; + print_indent " linux " . $k{"kernel"} . " " . $k{"append"} . "\n"; + print_indent " initrd $initrd\n"; + print_indent "}\n"; + } +} + +sub debug { +# print_indent $menudepth . " " . $menu{"number"} . ": " . $menu{"label"} . +# " '" . $menu{"title"} . "'\n"; +} + +sub create_theme_file { + my $filename = shift; + my @args; + push(@args, @cpp_and_opts); + push(@args, "-DTITLE=\"$tl_desc\""); + for (my $i = 0; $i < $menudepth; $i++) { + push(@args, "-DMENU$i=\"" . $menu_title[$i] . "\""); + } + push(@args, "$grub_theme"); + open(IN, "-|", @args) or die "Can't open cpp input: $!\n"; + open(OUT, ">", "$theme_dir/$filename") + or die "Can't create theme file $theme_dir/$filename: $!\n"; + while () { + print OUT "$_"; + } + close(IN); + close(OUT); +} + +make_path($theme_dir); +if (! -d $theme_dir) { + die "Can't make theme dir $theme_dir: $!\n"; +} +parse_file("isolinux.cfg"); + +$menu{"number"} = "1"; +$menu{"label"} = "top"; +$menu{"title"} = "Debian GNU/Linux Installer menu"; +$menu_title[$menudepth] = $menu{"title"}; + +my %kernel; +my $in_kernel = 0; +my $new_menu = 0; + +$menudepth++; +debug(); +print_indent "set theme=/boot/grub/theme/" . $menu{"number"} . "\n"; +create_theme_file($menu{"number"}); + +foreach my $line(@lines) { + if ($line =~ /^\s*menu begin\ (\S+)/) { + $menu_number[$menudepth]++; + $new_menu = 1; + my $mn_string = ""; + for(my $i = 0; $i <= $menudepth ; $i++) { + $mn_string .= "$menu_number[$i]"; + if ($i < $menudepth) { + $mn_string .= "-"; + } + } + $menu{"number"} = $mn_string; + $menu{"label"} = $1; + if ($in_kernel) { + print_kernel(\%kernel); + undef %kernel; + $in_kernel = 0; + } + } elsif ($line =~ /^\s*menu end/) { + if ($in_kernel) { + print_kernel(\%kernel); + undef %kernel; + $in_kernel = 0; + } + $menu_number[$menudepth] = 0; + $menudepth--; + if ($menudepth) { + print_indent "}\n"; + } + } elsif ($line =~ /^\s*menu title (.*$)/) { + if ($in_kernel) { + print_kernel(\%kernel); + undef %kernel; + $in_kernel = 0; + } + $menu{"title"} = $1; + if ($new_menu) { + print_indent "submenu '$gap" . $menu{"title"} . "\' {\n"; + $menu_title[$menudepth] = $menu{"title"}; + $menudepth++; + debug(); + print_indent "set theme=/boot/grub/theme/" . $menu{"number"} . "\n"; + create_theme_file($menu{"number"}); + $new_menu = 0; + } + } elsif ($line =~ /^label (\S*(rescue|install|auto|expert)\S*)/) { + if ($in_kernel) { + print_kernel(\%kernel); + undef %kernel; + } + $kernel{"ref"} = $1; + $in_kernel = 1; + } elsif ($line =~ /menu label (.*)$/ && $in_kernel) { + $kernel{"label"} = $1; + } elsif ($line =~ /menu default/ && $in_kernel) { + $kernel{"default"} = 1; + } elsif ($line =~ /kernel (.*)$/ && $in_kernel) { + $kernel{"kernel"} = $1; + } elsif ($line =~ /append (.*)$/ && $in_kernel) { + $kernel{"append"} = $1; + } else { + #print "$line\n"; + } +} +