[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH OSSTEST v2 19/19] Debian: Arrange to be able to chainload a xen.efi from grub2
Xen cannot (currently) be booted directly via the usual multiboot path on EFI systems of any arch. Instead it is necessary to either launch xen.efi direct from the UEFI shell or to chainload it from grub. In both cases the Xen command line as well as what would normally be the multiboot modules (kernel+command line, XSM policy, initrd) must be configured in a Xen configuration file. By patching overlay/etc/grub.d/20_linux_xen that if a suitable xen.efi is found in the EFI System Partition (as arrange by a previous patch) a suitable entry is created in grub.cfg as well. When parsing the grub.cfg look for such an entry into addition to the regular/multiboot one and when necessary write the configuration file based on the regular entry and return the chainload one such that it gets booted. This is currently enabled only for Jessie ARM64 systems. Note that the 20_linux_xen change here is a bit specific to us and not really generic enough to go upstream IMHO, hence I haven't. Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx> --- Osstest/Debian.pm | 75 +++++++++++++++++++++++++++++++++++++++-- overlay/etc/grub.d/20_linux_xen | 19 +++++++++++ 2 files changed, 92 insertions(+), 2 deletions(-) diff --git a/Osstest/Debian.pm b/Osstest/Debian.pm index d342103..c89a362 100644 --- a/Osstest/Debian.pm +++ b/Osstest/Debian.pm @@ -400,12 +400,18 @@ sub setupboot_grub2 ($$$$) { my $rmenu= '/boot/grub/grub.cfg'; my $kernkey= (defined $xenhopt ? 'KernDom0' : 'KernOnly'); - + + # Grub2 on Jessie/arm* doesn't do multiboot, so we must chainload. + my $need_uefi_chainload = + get_host_property($ho, "firmware") eq "uefi" && + $ho->{Suite} =~ m/jessie/ && $r{arch} =~ m/^arm/; + my $parsemenu= sub { my $f= bl_getmenu_open($ho, $rmenu, "$stash/$ho->{Name}--grub.cfg.1"); my @offsets = (0); my $entry; + my $chainentry; my $submenu; while (<$f>) { next if m/^\s*\#/ || !m/\S/; @@ -424,7 +430,13 @@ sub setupboot_grub2 ($$$$) { (defined $xenhopt ? qw(Title Hv KernDom0 KernVer) : qw(Title Hv KernOnly KernVer)); - if (@missing) { + if ($need_uefi_chainload && $entry->{Chainload}) { + # Needs to be before check of @missing, since a + # chained entry doesn't have anything useful in it + logm("Found chainload entry at $entry->{StartLine}..$."); + die "already got one" if $chainentry; + $chainentry = $entry; + } elsif (@missing) { logm("(skipping entry at $entry->{StartLine}..$.;". " no @missing)"); } elsif ($entry->{Hv} =~ m/xen-syms/) { @@ -456,9 +468,15 @@ sub setupboot_grub2 ($$$$) { $submenu={ StartLine =>$., MenuEntryPath => join ">", @offsets }; push @offsets,(0); } + if (m/^\s*chainloader\s*\/EFI\/osstest\/xen.efi/) { + die unless $entry; + $entry->{Hv}= $1; + $entry->{Chainload} = 1; + } if (m/^\s*multiboot\s*(?:\/boot)?\/(xen\S+)/) { die unless $entry; $entry->{Hv}= $1; + $entry->{Chainload} = 0; } if (m/^\s*multiboot\s*(?:\/boot)?\/(vmlinu[xz]-(\S+))\s+(.*)/) { die unless $entry; @@ -490,13 +508,66 @@ sub setupboot_grub2 ($$$$) { die unless $entry->{Hv}; } + if ($need_uefi_chainload) { + die 'chainload entry not found' unless $chainentry; + + # Propagate relevant fields of the main entry over to the + # chain entry for use of subsequent code. + foreach (qw(KernVer KernDom0 KernOnly KernOpts Initrd Xenpolicy)) { + next unless $entry->{$_}; + die if $chainentry->{$_}; + $chainentry->{$_} = $entry->{$_}; + } + + $entry = $chainentry; + } + return $entry; }; $bl->{UpdateConfig}= sub { my ( $ho ) = @_; + + target_editfile_root($ho, '/etc/default/grub', sub { + while (<::EI>) { + next if m/^export GRUB_ENABLE_XEN_UEFI_CHAINLOAD\=/; + print ::EO; + } + print ::EO "export GRUB_ENABLE_XEN_UEFI_CHAINLOAD=\"osstest\"\n" + if $need_uefi_chainload; + }); + target_cmd_root($ho, "update-grub"); + + if ($need_uefi_chainload) { + my $entry= $parsemenu->(); + my $xencfg = <<END; +[global] +default=osstest + +[osstest] +options=$xenhopt +kernel=vmlinuz $entry->{KernOpts} +END + $xencfg .= "ramdisk=initrd.gz\n" if $entry->{Initrd}; + $xencfg .= "xsm=xenpolicy\n" if $entry->{Xenpolicy}; + + target_putfilecontents_root_stash($ho,30,$xencfg,"/boot/efi/EFI/osstest/xen.cfg"); + + # /boot/efi should be a mounted EFI system partition, and + # /boot/efi/EFI/osstest/xen.efi should already exist. Hence no mkdir + # here. + target_cmd_root($ho, + <<END.($entry->{Initrd}?<<END:"").($entry->{Xenpolicy}?<<END:"")); + set -ex + cp -vL /boot/$entry->{KernDom0} /boot/efi/EFI/osstest/vmlinuz #/ +END + cp -vL /boot/$entry->{Initrd} /boot/efi/EFI/osstest/initrd.gz #/ +END + cp -vL /boot/$entry->{Xenpolicy} /boot/efi/EFI/osstest/xenpolicy #/ +END + } }; $bl->{GetBootKern}= sub { return $parsemenu->()->{$kernkey}; }; diff --git a/overlay/etc/grub.d/20_linux_xen b/overlay/etc/grub.d/20_linux_xen index aaead1b..7bee1a3 100755 --- a/overlay/etc/grub.d/20_linux_xen +++ b/overlay/etc/grub.d/20_linux_xen @@ -142,6 +142,25 @@ EOF } EOF } +chain_xen_entry () { + vendor="$1" + if [ ! -f /boot/efi/EFI/$vendor/xen.efi ] ; then + return + fi + title=$(gettext_quoted "Chainload $vendor Xen") + xmessage="$(gettext_printf "Chainloading $vendor Xen ...")" + printf "menuentry '${title}' ${CLASS} {\n" + prepare_grub_to_access_device `${grub_probe} --target=device /boot/efi/EFI/$vendor/xen.efi` | grub_add_tab + cat <<EOF + echo '$xmessage' + chainloader /EFI/$vendor/xen.efi +} +EOF +} + +for i in ${GRUB_ENABLE_XEN_UEFI_CHAINLOAD} ; do + chain_xen_entry $i +done linux_list=`for i in /boot/vmlinu[xz]-* /vmlinu[xz]-* /boot/kernel-*; do if grub_file_is_not_garbage "$i"; then -- 2.1.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |