-#!/usr/bin/env python
+#!/usr/bin/env python2
# -*- coding: utf-8 -*-
# pylint: disable-msg=C0302
"""
This script installs a Grml system (either a running system or ISO[s]) to a USB device
-:copyright: (c) 2009, 2010, 2011 by Michael Prokop <mika@grml.org>
+:copyright: (c) 2009-2019 by Michael Prokop <mika@grml.org>
:license: GPL v2 or any later version
:bugreports: http://grml.org/bugs/
setattr(opt_parser.values, option.dest, True)
setattr(opt_parser.values, 'syslinux', False)
+
# cmdline parsing
-USAGE = "Usage: %prog [options] <[ISO[s] | /lib/live/mount/medium]> </dev/sdX#>\n\
+USAGE = "Usage: %prog [options] <[ISO[s] | /run/live/medium]> </dev/sdX#>\n\
\n\
%prog installs Grml ISO[s] to an USB device to be able to boot from it.\n\
-Make sure you have at least one Grml ISO or a running Grml system (/lib/live/mount/medium),\n\
+Make sure you have at least one Grml ISO or a running Grml system (/run/live/medium),\n\
grub or syslinux and root access.\n\
\n\
Run %prog --help for usage hints, further information via: man grml2usb"
def get_function_name(obj):
- """Helper function for use in execute() to retrive name of a function
+ """Helper function for use in execute() to retrieve name of a function
@obj: the function object
"""
if efi_img:
mkdir(target + '/boot/')
exec_rsync(efi_img, target + '/boot/efi.img')
+ handle_secure_boot(target, efi_img)
for ffile in ['f%d' % number for number in range(1, 11)]:
search_and_copy(ffile, iso_mount, syslinux_target + ffile)
# copy all grub files from ISO
glob_and_copy(iso_mount + '/boot/grub/*', grub_target)
- # finally (after all GRUB files have been been installed) build static loopback.cfg
+ # finally (after all GRUB files have been installed) build static loopback.cfg
build_loopbackcfg(target)
version_files = search_file('grml-version', mountpath, lst_return=True)
if not version_files:
- if mountpath.startswith("/lib/live/mount/medium"):
+ if mountpath.startswith("/run/live/medium"):
logging.critical("Error: could not find grml-version file.")
logging.critical("Looks like your system is running from RAM but required files are not available.")
logging.critical("Please either boot without toram=... or use boot option toram instead of toram=...")
logging.debug("Updating grub configuration")
grub_target = target + '/boot/grub/'
+ secureboot_target = target + '/EFI/ubuntu/'
bootid_re = re.compile("bootid=[\w_-]+")
live_media_path_re = re.compile("live-media-path=[\w_/-]+")
remove_regexes.append(re.compile(regex))
shortname = get_shortname(grml_flavour)
- for filename in glob.glob(grub_target + '*.cfg'):
+ for filename in glob.glob(grub_target + '*.cfg') + glob.glob(secureboot_target + '*.cfg'):
for line in fileinput.input(filename, inplace=1):
line = line.rstrip("\r\n")
if option_re.search(line):
if shortname in filename:
line = live_media_path_re.sub('', line)
line = line.rstrip() + ' live-media-path=/live/%s/ ' % (grml_flavour)
+ if bootopt.strip():
+ line = line.replace(' {} '.format(bootopt.strip()), ' ')
+ if line.endswith(bootopt):
+ line = line[:-len(bootopt)]
line = line.rstrip() + r' bootid=%s %s ' % (UUID, bootopt)
for regex in remove_regexes:
line = regex.sub(' ', line)
def initial_syslinux_config(target):
- """Generates intial syslinux configuration
+ """Generates initial syslinux configuration
@target path of syslinux's configuration files"""
add_syslinux_entry("%s/additional.cfg" % syslinux_target, flavour_filename)
+def handle_secure_boot(target, efi_img):
+ """Provide secure boot support by extracting files from /boot/efi.img
+
+ @target: path where grml's main files should be copied to
+ @efi_img: path to the efi.img file that includes the files for secure boot
+ """
+
+ mkdir(target + '/efi/boot/')
+ efi_mountpoint = tempfile.mkdtemp(prefix="grml2usb", dir=os.path.abspath(options.tmpdir))
+ logging.debug("efi_mountpoint = %s" % efi_mountpoint)
+ register_tmpfile(efi_mountpoint)
+
+ try:
+ logging.debug("mount(%s, %s, ['-o', 'ro', '-t', 'vfat']" % (efi_img, efi_mountpoint))
+ mount(efi_img, efi_mountpoint, ['-o', 'ro', '-t', 'vfat'])
+ except CriticalException as error:
+ logging.critical("Fatal: %s", error)
+ sys.exit(1)
+
+ ubuntu_cfg = search_file('grub.cfg', efi_mountpoint + '/EFI/ubuntu')
+ logging.debug("ubuntu_cfg = %s" % ubuntu_cfg)
+ if not ubuntu_cfg:
+ logging.info("No /EFI/ubuntu/grub.cfg found inside EFI image, looks like Secure Boot support is missing.")
+ else:
+ mkdir(target + '/efi/ubuntu')
+ logging.debug("exec_rsync(%s, %s + '/efi/ubuntu/grub.cfg')" % (ubuntu_cfg, target))
+ exec_rsync(ubuntu_cfg, target + '/efi/ubuntu/grub.cfg')
+
+ logging.debug("exec_rsync(%s + '/EFI/BOOT/grubx64.efi', %s + '/efi/boot/grubx64.efi')'" % (efi_mountpoint, target))
+ exec_rsync(efi_mountpoint + '/EFI/BOOT/grubx64.efi', target + '/efi/boot/grubx64.efi')
+
+ # NOTE - we're overwriting /efi/boot/bootx64.efi from copy_bootloader_files here
+ logging.debug("exec_rsync(%s + '/EFI/BOOT/bootx64.efi', %s + '/efi/boot/bootx64.efi')'" % (efi_mountpoint, target))
+ exec_rsync(efi_mountpoint + '/EFI/BOOT/bootx64.efi', target + '/efi/boot/bootx64.efi')
+
+ try:
+ unmount(efi_mountpoint, "")
+ logging.debug('Unmounted %s' % efi_mountpoint)
+ os.rmdir(efi_mountpoint)
+ logging.debug('Removed directory %s' % efi_mountpoint)
+ except StandardError:
+ logging.critical('RuntimeError while umount %s' % efi_mountpoint)
+ sys.exit(1)
+
+
def handle_bootloader_config(grml_flavour, device, target):
"""Main handler for generating bootloader's configuration
def install_grml(mountpoint, device):
"""Main logic for copying files of the currently running Grml system.
- @mountpoint: directory where currently running live system resides (usually /lib/live/mount/medium)
+ @mountpoint: directory where currently running live system resides (usually /run/live/medium)
@device: partition where the specified ISO should be installed to"""
device_mountpoint = device
def check_options(opts):
- """Check compability of provided user opts
+ """Check compatibility of provided user opts
@opts option dict from OptionParser
"""