liveusb: EFI support
Since livecd-tools doesn't support starting Xen in EFI mode, most of its EFI support is rewritten here (overriden in LiveEFIImageCreator, based on imgcreate.LiveImageCreator). This all is still temporary solution, until Xen will have mutiboot2+EFI support - then almost standard configuration could be used (almost the same grub config as for legacy boot). So keep the changes here, and when the proper solution would be implemented, pursue to having it upstream. QubesOS/qubes-issues#794
This commit is contained in:
parent
9a80875a5d
commit
0493bb717c
@ -33,8 +33,7 @@ anaconda
|
||||
|
||||
qubes-live
|
||||
|
||||
# FIXME: xen.efi not supported by livecd-tools, disable it for now
|
||||
-shim
|
||||
shim
|
||||
|
||||
%end
|
||||
|
||||
|
@ -11,6 +11,10 @@ Group: System
|
||||
License: GPL
|
||||
URL: https://qubes-os.org
|
||||
|
||||
# ensure that the whole %%post is run when xen and kernel are already installed
|
||||
Requires(post): xen-hypervisor
|
||||
Requires(post): kernel
|
||||
|
||||
%description
|
||||
Various fixes for Qubes Live edition
|
||||
|
||||
@ -49,6 +53,22 @@ for kernel in /boot/vmlinuz-*; do
|
||||
ln -s $(basename ${xen}) /boot/xen.gz-${short_version}
|
||||
done
|
||||
|
||||
# EFI: prepare small version of initrd to fit in 32MB ISO9660 limit
|
||||
xen=$(ls -1 /boot/efi/EFI/qubes/xen-*.efi | tail -n 1)
|
||||
if [ -n "$xen" ]; then
|
||||
kernel=$(ls -1 /boot/vmlinuz-*|sort -n|tail -n 1)
|
||||
cp "${kernel}" /boot/efi/EFI/qubes/vmlinuz
|
||||
version=$(echo ${kernel} | cut -f 2- -d -)
|
||||
# copy from lorax-templates-qubes/templates/efi.tmpl:
|
||||
scsi_modules="3w-9xxx 3w-sas 3w-xxxx BusLogic a100u2w aacraid advansys aic79xx aic7xxx am53c974 arcmsr atp870u bfa bnx2fc csiostor dc395x dmx3191d esas2r esp_scsi fcoe fnic gdth hpsa hptiop hv_storvsc initio ipr ips isci iscsi_boot_sysfs libfc libfcoe libiscsi libosd libsas lpfc megaraid megaraid_mbox megaraid_mm megaraid_sas mpt2sas mpt3sas mvsas mvumi osd pm80xx pmcraid qla1280 qla2xxx qla4xxx raid_class scsi_debug scsi_dh_emc scsi_dh_rdac scsi_transport_fc scsi_transport_iscsi scsi_transport_sas scsi_transport_spi scsi_transport_srp stex sym53c8xx ufshcd virtio_scsi vmw_pvscsi wd719x"
|
||||
extra_modules="affs befs coda cuse dlm gfs2 mptfc ncpfs nilfs2 ocfs2 ocfs2_dlm ocfs2_dlmfs ocfs2_nodemanager ocfs2_stack_o2cb ocfs2_stack_user ocfs2_stackglue sctp sysv ubifs ufs"
|
||||
dracut --nomdadmconf --nolvmconf --xz \
|
||||
--omit "network multipath modsign systemd crypt shutdown plymouth" \
|
||||
--omit "fcoe fcoe-uefi nfs iscsi ifcfg" \
|
||||
--omit-drivers="${scsi_modules}" \
|
||||
--omit-drivers="${extra_modules}" \
|
||||
/boot/efi/EFI/qubes/initrd-small.img ${version}
|
||||
fi
|
||||
|
||||
%files
|
||||
/etc/rc.d/init.d/livesys
|
||||
|
@ -19,18 +19,227 @@
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import glob
|
||||
import shutil
|
||||
import stat
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import optparse
|
||||
import logging
|
||||
|
||||
import imgcreate
|
||||
from imgcreate.fs import makedirs
|
||||
|
||||
class Usage(Exception):
|
||||
def __init__(self, msg = None, no_error = False):
|
||||
Exception.__init__(self, msg, no_error)
|
||||
|
||||
class LiveEFIImageCreator(imgcreate.LiveImageCreator):
|
||||
|
||||
def _get_mkisofs_options(self, isodir):
|
||||
options = [ "-b", "isolinux/isolinux.bin",
|
||||
"-c", "isolinux/boot.cat",
|
||||
"-no-emul-boot", "-boot-info-table",
|
||||
"-boot-load-size", "4" ]
|
||||
if os.path.exists(isodir + "/isolinux/efiboot.img"):
|
||||
options.extend([ "-eltorito-alt-boot",
|
||||
"-e", "isolinux/efiboot.img",
|
||||
"-no-emul-boot"])
|
||||
if os.path.exists(isodir + "/isolinux/macboot.img"):
|
||||
options.extend([ "-eltorito-alt-boot",
|
||||
"-e", "isolinux/macboot.img",
|
||||
"-no-emul-boot"])
|
||||
return options
|
||||
|
||||
def __copy_efi_files(self, isodir):
|
||||
""" Copy the efi files into /EFI/BOOT/
|
||||
If any of them are missing, return False.
|
||||
requires:
|
||||
xen.efi
|
||||
gcdx64.efi
|
||||
vmlinuz
|
||||
initrd
|
||||
"""
|
||||
fail = False
|
||||
missing = []
|
||||
# XXX: when adding multiple kernel support, vmlinuz and initrd needs to
|
||||
# be suffixed with index
|
||||
files = [("/boot/efi/EFI/*/shim.efi", "/EFI/BOOT/BOOT%s.efi" % (self.efiarch,)),
|
||||
("/boot/efi/EFI/*/gcd*.efi", "/EFI/BOOT/grubx64.efi"),
|
||||
("/boot/efi/EFI/*/xen-*.efi", "/EFI/BOOT/xen.efi"),
|
||||
("/boot/efi/EFI/*/vmlinuz", "/EFI/BOOT/vmlinuz"),
|
||||
("/boot/efi/EFI/*/initrd-small.img", "/EFI/BOOT/initrd"),
|
||||
("/boot/efi/EFI/*/fonts/unicode.pf2", "/EFI/BOOT/fonts/"),
|
||||
]
|
||||
makedirs(isodir+"/EFI/BOOT/fonts/")
|
||||
for src, dest in files:
|
||||
src_glob = glob.glob(self._instroot+src)
|
||||
if not src_glob:
|
||||
missing.append("Missing EFI file (%s)" % (src,))
|
||||
fail = True
|
||||
else:
|
||||
shutil.copy(src_glob[0], isodir+dest)
|
||||
map(logging.error, missing)
|
||||
return fail
|
||||
|
||||
|
||||
def __get_xen_efi_image_stanza(self, **args):
|
||||
if self._isDracut:
|
||||
args["rootlabel"] = "live:LABEL=%(fslabel)s" % args
|
||||
else:
|
||||
args["rootlabel"] = "CDLABEL=%(fslabel)s" % args
|
||||
return """[%(name)s%(index)s]
|
||||
kernel=vmlinuz%(index)s root=%(rootlabel)s %(liveargs)s %(extra)s
|
||||
ramdisk=initrd%(index)s
|
||||
|
||||
""" %args
|
||||
|
||||
|
||||
def __get_efi_image_stanza(self, **args):
|
||||
return """menuentry '%(long)s' --class qubes --class gnu-linux --class gnu --class os {
|
||||
chainloader /efi/boot/xen.efi placeholder %(name)s%(index)s
|
||||
}
|
||||
""" %args
|
||||
|
||||
def __get_efi_image_stanzas(self, isodir, name):
|
||||
# FIXME: this only supports one kernel right now...
|
||||
|
||||
kernel_options = self._get_kernel_options()
|
||||
checkisomd5 = self._has_checkisomd5()
|
||||
|
||||
cfg = ""
|
||||
|
||||
for index in range(0, 9):
|
||||
# only one supported anyway, so simply drop the suffix
|
||||
index = ""
|
||||
cfg += self.__get_efi_image_stanza(long = "Start " + self.product,
|
||||
index = index, name = "normal")
|
||||
if checkisomd5:
|
||||
cfg += self.__get_efi_image_stanza(
|
||||
long = "Test this media & start " + self.product,
|
||||
index = index, name = "check")
|
||||
cfg += """
|
||||
submenu 'Troubleshooting -->' {
|
||||
"""
|
||||
cfg += self.__get_efi_image_stanza(long = "Start " + self.product + " in basic graphics mode",
|
||||
index = index, name = "basicvideo")
|
||||
|
||||
cfg+= """}
|
||||
"""
|
||||
break
|
||||
|
||||
return cfg
|
||||
|
||||
def __get_xen_efi_image_stanzas(self, isodir, name):
|
||||
# FIXME: this only supports one kernel right now...
|
||||
|
||||
kernel_options = self._get_kernel_options()
|
||||
checkisomd5 = self._has_checkisomd5()
|
||||
|
||||
cfg = ""
|
||||
|
||||
for index in range(0, 9):
|
||||
# only one supported anyway, so simply drop the suffix
|
||||
index = ""
|
||||
cfg += self.__get_xen_efi_image_stanza(fslabel = self.fslabel,
|
||||
liveargs = kernel_options,
|
||||
long = "Start " + self.product,
|
||||
extra = "", index = index,
|
||||
name = "normal")
|
||||
if checkisomd5:
|
||||
cfg += self.__get_xen_efi_image_stanza(fslabel = self.fslabel,
|
||||
liveargs = kernel_options,
|
||||
long = "Test this media & start " + self.product,
|
||||
extra = "rd.live.check",
|
||||
index = index, name = "check")
|
||||
cfg += self.__get_xen_efi_image_stanza(fslabel = self.fslabel,
|
||||
liveargs = kernel_options,
|
||||
long = "Start " + self.product + " in basic graphics mode",
|
||||
extra = "nomodeset", index = index,
|
||||
name = "basicvideo")
|
||||
|
||||
break
|
||||
|
||||
return cfg
|
||||
|
||||
def __get_basic_xen_efi_config(self):
|
||||
return """
|
||||
[global]
|
||||
default=normal
|
||||
"""
|
||||
|
||||
def __get_basic_efi_config(self, **args):
|
||||
return """
|
||||
set default="0"
|
||||
|
||||
function load_video {
|
||||
insmod efi_gop
|
||||
insmod efi_uga
|
||||
insmod video_bochs
|
||||
insmod video_cirrus
|
||||
insmod all_video
|
||||
}
|
||||
|
||||
load_video
|
||||
set gfxpayload=keep
|
||||
insmod gzio
|
||||
insmod part_gpt
|
||||
insmod ext2
|
||||
|
||||
set timeout=%(timeout)d
|
||||
### END /etc/grub.d/00_header ###
|
||||
|
||||
# do not use 'search' - root should be already set based on grub.efi location
|
||||
|
||||
### BEGIN /etc/grub.d/10_linux ###
|
||||
""" %args
|
||||
|
||||
def _configure_efi_bootloader(self, isodir):
|
||||
"""Set up the configuration for an EFI bootloader"""
|
||||
if self.__copy_efi_files(isodir):
|
||||
shutil.rmtree(isodir + "/EFI")
|
||||
logging.warn("Failed to copy EFI files, no EFI Support will be included.")
|
||||
return
|
||||
|
||||
cfg = self.__get_basic_efi_config(isolabel = self.fslabel,
|
||||
timeout = self._timeout)
|
||||
cfg += self.__get_efi_image_stanzas(isodir, self.name)
|
||||
|
||||
xen_cfg = self.__get_basic_xen_efi_config()
|
||||
xen_cfg += self.__get_xen_efi_image_stanzas(isodir, self.name)
|
||||
|
||||
cfgf = open(isodir + "/EFI/BOOT/grub.cfg", "w")
|
||||
cfgf.write(cfg)
|
||||
cfgf.close()
|
||||
|
||||
xen_cfgf = open(isodir + "/EFI/BOOT/xen.cfg", "w")
|
||||
xen_cfgf.write(xen_cfg)
|
||||
xen_cfgf.close()
|
||||
|
||||
def _generate_efiboot(self, isodir):
|
||||
"""Generate EFI boot images."""
|
||||
if not glob.glob(self._instroot+"/boot/efi/EFI/*/xen-*.efi"):
|
||||
logging.error("Missing xen-*.efi, skipping efiboot.img creation.")
|
||||
return
|
||||
|
||||
subprocess.call(["mkefiboot", "--label", "QUBESEFI", isodir + "/EFI/BOOT",
|
||||
isodir + "/isolinux/efiboot.img"])
|
||||
# FIXME: replace icon
|
||||
# FIXME: this is broken for many reasons:
|
||||
# - mkefiboot generates unnecessary big image (about 4 times bigger
|
||||
# than required) - the bug is in mkmacboot function:
|
||||
# size = estimate_size(bootdir, graft=graft) * 2
|
||||
# ^^^^^^^^^^^^^^^^^^^^ already counted twice
|
||||
# - mkefiboot -a assumes that the loader is grub.efi
|
||||
# - it isn't clear whether xen.efi would even work on Apple
|
||||
subprocess.call(["mkefiboot", "-a", isodir + "/EFI/BOOT",
|
||||
isodir + "/isolinux/macboot.img", "-l", self.product,
|
||||
"-n", "/usr/share/pixmaps/bootloader/fedora-media.vol",
|
||||
"-i", "/usr/share/pixmaps/bootloader/fedora.icns",
|
||||
"-p", self.product])
|
||||
|
||||
|
||||
def parse_options(args):
|
||||
parser = optparse.OptionParser()
|
||||
|
||||
@ -181,7 +390,7 @@ def main():
|
||||
|
||||
try:
|
||||
if options.image_type == 'livecd':
|
||||
creator = imgcreate.LiveImageCreator(ks, name,
|
||||
creator = LiveEFIImageCreator(ks, name,
|
||||
fslabel=fslabel,
|
||||
releasever=options.releasever,
|
||||
tmpdir=os.path.abspath(options.tmpdir),
|
||||
|
Loading…
Reference in New Issue
Block a user