From aa0972e2c62feff98273c6a1575e148817b2fe0e Mon Sep 17 00:00:00 2001 From: Neil Williams Date: Tue, 18 Aug 2015 13:11:58 +0200 Subject: Add examples for UEFI hook. Document task package usage in the README --- TODO | 37 +++++++++++++++++++++++++++++++ bin/vmdebootstrap | 45 +++++++++++++++++++++---------------- examples/README.txt | 50 ++++++++++++++++++++++++++++++++++++++++++ examples/jessie-uefi-amd64.sh | 15 +++++++++++++ examples/qemu-efi-bochs-drm.sh | 8 +++++++ vmdebootstrap/base.py | 13 +++++++++++ vmdebootstrap/filesystem.py | 5 +++++ vmdebootstrap/uefi.py | 2 ++ 8 files changed, 156 insertions(+), 19 deletions(-) create mode 100644 TODO create mode 100755 examples/jessie-uefi-amd64.sh create mode 100755 examples/qemu-efi-bochs-drm.sh diff --git a/TODO b/TODO new file mode 100644 index 0000000..a1cd415 --- /dev/null +++ b/TODO @@ -0,0 +1,37 @@ +TODO +==== + +* document the problems of setting a default password + +* first-boot customisation support (via a package) which forces a + new password, possibly new hostname, generate new ssh key etc. + +* make all internal additions and operations optional + +* investigate some way to support complex partitioning + +* document that no-kernel can lead to images where the kernel + cannot be upgraded. + +* try to support upgrading the bootloader + possibly via the config output + problems of flash-kernel + +* automatically grow rootfs to media size on first boot + boot into ramdisk, umount media, move ext4 along media + expand vfat. + +* document of how to add new bootloader etc. + unless the old and new bootloader exist as packages, this + is going to be manual. + +* customisations as packages. + +* document how the image was built with the config called. + include the config output and a copy of the script with + dependencies. + +* consider limitations of only one hook script + likely to be a lack of time to implement multi-hook support. + +* support method to share shell customisation scripts diff --git a/bin/vmdebootstrap b/bin/vmdebootstrap index 2dc46a4..a5cec40 100755 --- a/bin/vmdebootstrap +++ b/bin/vmdebootstrap @@ -283,10 +283,12 @@ class VmDebootstrap(cliapp.Application): # pylint: disable=too-many-public-meth filesystem = self.handlers[Filesystem.name] if self.settings['use-uefi']: bootdir = self.bootdir - logging.debug("rootdir=%s rootdev=%s bootdir=%s", rootdir, rootdev, bootdir) + logging.debug( + "rootdir=%s rootdev=%s bootdir=%s", + rootdir, rootdev, bootdir) logging.debug(runcmd(['mount'])) if not os.path.ismount(bootdir): - self.logging.warning("%s had to be remounted", bootdir) + logging.warning("%s had to be remounted", bootdir) self.mount(bootdir) grub.install_grub_uefi(rootdir) uefi.configure_efi(rootdir) @@ -379,23 +381,17 @@ class VmDebootstrap(cliapp.Application): # pylint: disable=too-many-public-meth """ base = self.handlers[Base.name] base.message('Creating partitions') + uefi = self.handlers[Uefi.name] runcmd(['parted', '-s', self.settings['image'], 'mklabel', self.settings['part-type']]) partoffset = 0 - extent = '100%' - swap = 256 * 1024 * 1024 - if self.settings['swap'] > 0: - if self.settings['swap'] > swap: - swap = self.settings['swap'] - else: - # minimum 256Mb as default qemu ram is 128Mb - logging.debug("Setting minimum 256Mb swap space") - extent = "%s%%" % int(100 * (self.settings['size'] - swap) / self.settings['size']) + extent = base.check_swap_size() - if self.settings['use-uefi']: - uefi = self.handlers[Uefi.name] - uefi.partition_esp() + # uefi + uefi.partition_esp() + # /boot partitioning offset calculation + # returns partoffset if self.settings['bootoffset'] and self.settings['bootoffset'] is not '0': # turn v.small offsets into something at least possible to create. if self.settings['bootoffset'] < 1048576: @@ -405,7 +401,12 @@ class VmDebootstrap(cliapp.Application): # pylint: disable=too-many-public-meth partoffset, self.settings['bootoffset']) else: partoffset = self.settings['bootoffset'] / (1024 * 1024) - base.message("Using bootoffset: %smib %s bytes" % (partoffset, self.settings['bootoffset'])) + base.message( + "Using bootoffset: %smib %s bytes" % + (partoffset, self.settings['bootoffset'])) + + # /boot creation - move into base but keep the check + # needs extent, partoffset, bootsize: no return if self.settings['bootsize'] and self.settings['bootsize'] is not '0%': if self.settings['grub'] and not partoffset: partoffset = 1 @@ -418,19 +419,25 @@ class VmDebootstrap(cliapp.Application): # pylint: disable=too-many-public-meth logging.debug("Starting root partition at %sMb", partoffset) runcmd(['parted', '-s', self.settings['image'], 'mkpart', 'primary', str(bootsize), extent]) + + # uefi - make rootfs partition after end of ESP + # needs extent elif self.settings['use-uefi']: bootsize = self.settings['esp-size'] / (1024 * 1024) + 1 runcmd(['parted', '-s', self.settings['image'], 'mkpart', 'primary', str(bootsize), extent]) + + # no boot partition else: runcmd(['parted', '-s', self.settings['image'], 'mkpart', 'primary', '0%', extent]) + + # whatever we create, something needs the boot flag runcmd(['parted', '-s', self.settings['image'], 'set', '1', 'boot', 'on']) - if self.settings['swap'] > 0: - logging.debug("Creating swap partition") - runcmd(['parted', '-s', self.settings['image'], - 'mkpart', 'primary', 'linux-swap', extent, '100%']) + + # return to doing swap setup + base.make_swap(extent) def _bootstrap_packages(self): # pylint: disable=too-many-branches uefi = self.handlers[Uefi.name] diff --git a/examples/README.txt b/examples/README.txt index cde28cf..65e6bd9 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -30,3 +30,53 @@ CubieTruck ---------- Currently untested and lacking u-boot support. + +QEMU and EFI +------------ + +The bochs-drm kernel driver can be a problem when testing UEFI images, +even headless ones, causing systemd to halt before a login prompt is +offered. + +vmdebootstrap includes a simple customisation script which blacklists +the bochs-drm module. Use, copy or extend this script for any image +which uses UEFI and which should be testable using QEMU. + +To run UEFI with QEMU, the ovmf package needs to be installed from +non-free (due to patent issues with VFAT) and the -L option used to +QEMU to indicate the directory containing the EFI firmware to use. +For amd64, the firmware installed by ovmf can need to be renamed +(or symlinked) as /usr/share/ovmf/bios-256k.bin - then supply the +-L option to QEMU: + +$ qemu-system-x86_64 -machine accel=kvm -m 4096 -smp 2 -drive format=raw,file=test.img -L /usr/share/ovmf/ + +debootstrap and task packages +----------------------------- + +debootstrap is designed to be a minimalist tool and vmdebootstrap +wraps this support without substantial changes. Task packages are +the simplest way to extend a minimal bootstrap to a more general +purpose machine but there are limitations. debootstrap does not +handle Recommended packages, so installing a task package using +the --package support of vmdebootstrap (just as with the --include +support of debootstrap itself) may result in a system with fewer +packages installed than expected. Such systems can have the extra +packages identified after boot using graphical tools like aptitude +but to have all packages available during the creation of the image, +a customisation hook is required. The hook simply needs to install +the task package using apt instead of passing the task package to +--package. This allows apt to do all the normal Recommends calculations +and results in all of the extra packages being installed in one +operation. However, the apt source used for this will be the apt +source specified to vmdebootstrap for use after the system is booted, +so you may also want to extend the hook to temporarily reinstate a +local mirror (as used for the bootstrap phase) and put the other +mirror back at the end of the hook. + +Examples of such hooks are available here: +http://anonscm.debian.org/cgit/debian-cd/pettersson-live.git/tree/vmdebootstrap + +(These will need modification for other uses as the hooks expect +a particular filesystem layout only useful for debian-cd.) + diff --git a/examples/jessie-uefi-amd64.sh b/examples/jessie-uefi-amd64.sh new file mode 100755 index 0000000..0578450 --- /dev/null +++ b/examples/jessie-uefi-amd64.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +set -e + +WHO=`whoami` +sudo vmdebootstrap --owner ${WHO} --verbose \ + --sudo --lock-root-password \ + --enable-dhcp --configure-apt \ + --log amd64-uefi.log --log-level debug \ + --size 5G --distribution jessie \ + --grub --use-uefi \ + --package task-xfce-desktop \ + --customize ./examples/qemu-efi-bochs-drm.sh \ + "$@" + diff --git a/examples/qemu-efi-bochs-drm.sh b/examples/qemu-efi-bochs-drm.sh new file mode 100755 index 0000000..d7b7a58 --- /dev/null +++ b/examples/qemu-efi-bochs-drm.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +set -e + +rootdir=$1 + +echo "blacklist bochs-drm" > $rootdir/etc/modprobe.d/qemu-blacklist.conf + diff --git a/vmdebootstrap/base.py b/vmdebootstrap/base.py index e840855..be51ce6 100644 --- a/vmdebootstrap/base.py +++ b/vmdebootstrap/base.py @@ -165,3 +165,16 @@ class Base(object): # to autologin, serial_command can contain '-a root' with open(inittab, 'a') as ftab: ftab.write('\nS0:23:respawn:%s\n' % serial_command) + + def check_swap_size(self): + # swap - modifies extent + extent = '100%' + swap = 256 * 1024 * 1024 + if self.settings['swap'] > 0: + if self.settings['swap'] > swap: + swap = self.settings['swap'] + else: + # minimum 256Mb as default qemu ram is 128Mb + logging.debug("Setting minimum 256Mb swap space") + extent = "%s%%" % int(100 * (self.settings['size'] - swap) / self.settings['size']) + return extent diff --git a/vmdebootstrap/filesystem.py b/vmdebootstrap/filesystem.py index ccc95a4..796f7d8 100644 --- a/vmdebootstrap/filesystem.py +++ b/vmdebootstrap/filesystem.py @@ -291,3 +291,8 @@ class Filesystem(Base): fhosts.write('%s\n' % line) except IOError: pass + + def make_rootfs_part(self, extent): + bootsize = self.settings['esp-size'] / (1024 * 1024) + 1 + runcmd(['parted', '-s', self.settings['image'], + 'mkpart', 'primary', str(bootsize), extent]) diff --git a/vmdebootstrap/uefi.py b/vmdebootstrap/uefi.py index 2a8bc2a..7f77f9f 100644 --- a/vmdebootstrap/uefi.py +++ b/vmdebootstrap/uefi.py @@ -105,6 +105,8 @@ class Uefi(Base): umount_wrapper(rootdir) def partition_esp(self): + if not self.settings['use-uefi']: + return espsize = self.settings['esp-size'] / (1024 * 1024) self.message("Using ESP size: %smib %s bytes" % (espsize, self.settings['esp-size'])) runcmd(['parted', '-s', self.settings['image'], -- cgit v1.2.1