From 7ebb3d11d92755e65ab3854f73291726c3567c7f Mon Sep 17 00:00:00 2001 From: Thomas Backlund <tmb@mageia.org> Date: Sat, 19 Oct 2013 19:27:20 +0100 Subject: [PATCH] mgalive: A module to mount Mageia Live media Updated to work with overlay from 3.19 Signed-off-by: Thomas Backlund <tmb@mageia.org> Updated to support persistence and multi-boot USB sticks. Signed-off-by: Martin Whitaker <mageia@martin-whitaker.me.uk> Updated to eject CD and pause on shutdown. Signed-off-by: Martin Whitaker <mageia@martin-whitaker.me.uk> Updated to support encrypted persistent partition and fix mga#25924. Signed-off-by: Martin Whitaker <mageia@martin-whitaker.me.uk> Updated to handle /dev/disk/by-label linking to base device, not first partition (mga#27638). Signed-off-by: Martin Whitaker <mageia@martin-whitaker.me.uk> Updated to add boot option to temporarily disable persistence (mga#27674). Signed-off-by: Martin Whitaker <mageia@martin-whitaker.me.uk> Updated to ensure udev has re-added the protective partition before trying to mount it (mga#27638). Signed-off-by: Martin Whitaker <mageia@martin-whitaker.me.uk> Updated to ensure shutdown message is displayed on current tty. Signed-off-by: Martin Whitaker <mageia@martin-whitaker.me.uk> diff --git a/modules.d/90mgalive/mgalive-genrules.sh b/modules.d/90mgalive/mgalive-genrules.sh new file mode 100755 index 00000000..f450ebfa --- /dev/null +++ b/modules.d/90mgalive/mgalive-genrules.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +case "$root" in + mgalive:/dev/*) + { + printf 'KERNEL=="%s", RUN+="/sbin/initqueue --settled --onetime --unique /sbin/mgalive-root $env{DEVNAME}"\n' \ + ${root#mgalive:/dev/} + printf 'SYMLINK=="%s", RUN+="/sbin/initqueue --settled --onetime --unique /sbin/mgalive-root $env{DEVNAME}"\n' \ + ${root#mgalive:/dev/} + } >> /etc/udev/rules.d/99-mgalive.rules + wait_for_dev "${root#mgalive:}" + ;; + mgalive:*) + if [ -f "${root#mgalive:}" ]; then + /sbin/initqueue --settled --onetime --unique /sbin/mgalive-root "${root#mgalive:}" + fi + ;; +esac diff --git a/modules.d/90mgalive/mgalive-parse.sh b/modules.d/90mgalive/mgalive-parse.sh new file mode 100755 index 00000000..c5225ba4 --- /dev/null +++ b/modules.d/90mgalive/mgalive-parse.sh @@ -0,0 +1,31 @@ +#!/bin/sh +# live images are specified with +# root=mgalive:backingdev + +[ -z "$root" ] && root=$(getarg root=) + +if [ "${root%%:*}" = "mgalive" ] ; then + liveroot=$root +fi + +[ "${liveroot%%:*}" = "mgalive" ] || return + +modprobe -q loop + +case "$liveroot" in + mgalive:LABEL=*|LABEL=*) \ + root="${root#mgalive:}" + root="$(echo $root | sed 's,/,\\x2f,g')" + root="mgalive:/dev/disk/by-label/${root#LABEL=}" + rootok=1 ;; + mgalive:UUID=*|UUID=*) \ + root="${root#mgalive:}" + root="mgalive:/dev/disk/by-uuid/${root#UUID=}" + rootok=1 ;; +esac +info "root was $liveroot, is now $root" + +# make sure that init doesn't complain +[ -z "$root" ] && root="mgalive" + +wait_for_dev /live/union diff --git a/modules.d/90mgalive/mgalive-quit-plymouth.sh b/modules.d/90mgalive/mgalive-quit-plymouth.sh new file mode 100755 index 00000000..50fe9532 --- /dev/null +++ b/modules.d/90mgalive/mgalive-quit-plymouth.sh @@ -0,0 +1,6 @@ +#!/bin/sh +if [ -x /bin/plymouth ] ; then + /bin/plymouth --quit + /bin/plymouth --wait +fi +return 0 diff --git a/modules.d/90mgalive/mgalive-root.sh b/modules.d/90mgalive/mgalive-root.sh new file mode 100755 index 00000000..5ae05e8c --- /dev/null +++ b/modules.d/90mgalive/mgalive-root.sh @@ -0,0 +1,163 @@ +#!/usr/bin/sh + +. /lib/dracut-lib.sh + +can_decrypt=0 +if [ -f /lib/dracut-crypt-lib.sh ] ; then + . /lib/dracut-crypt-lib.sh + can_decrypt=1 +fi + +[ -f /tmp/root.info ] && . /tmp/root.info + +PATH=/usr/sbin:/usr/bin:/sbin:/bin + +[ -z "$1" ] && exit 1 +livedev="$1" + +# Create the live tree +mkdir -m 0755 -p /live/distrib +mkdir -m 0755 -p /live/media +mkdir -m 0755 -p /live/overlay +mkdir -m 0755 -p /live/union +mkdir -m 0755 -p /run/mgalive/ovlsize + +# Get the base device name +basedev=$(echo $livedev | sed -e 's,\(/dev/sd[a-z]\)1,\1,g' -e 's,\(/dev/mmcblk[0-9]\)p1,\1,g') +# Make it available to draklive-install and mgalive-shutdown +echo $basedev > /run/mgalive/basedev + +# Unlock any encrypted partitions on the base device +if [ $can_decrypt -eq 1 ] ; then + for dev in $(blkid -t TYPE=crypto_LUKS -o device | grep $basedev) ; do + ask_for_password \ + --ply-cmd "cryptsetup open -T1 $dev crypt_${dev##/dev/}" \ + --ply-prompt "Password ($dev)" \ + --ply-tries 3 \ + --tty-cmd "cryptsetup open -T3 $dev crypt_${dev##/dev/}" \ + --tty-tries 1 + done +fi + +# Get the base directory for locating the loopback file. In normal use this is +# the root directory, but a multi-boot USB stick may want to override this. +basedir=$(getarg mgalive.basedir) + +# Get the device or path used for persistent storage (if it exists). In normal +# use this is another partition on the same base device, but a multi-boot USB +# stick may want to override this. +overlay=$(getarg mgalive.overlay) +if [ -z "$overlay" ] ; then + overlay=$(blkid -t LABEL=mgalive-persist -o device | grep $basedev'\|'/dev/mapper) +elif [ "$overlay" = "ram" ] ; then + overlay= +else + overlay=$livedev$overlay +fi + +# If the base device is partitioned (i.e. it's a USB stick, not a DVD), get the +# device name and start offset of the first partition. This is the protective +# partition covering the iso9660 filesystem. +if [ $livedev = $basedev ] ; then + ps=0 + case $basedev in + /dev/sd*) + test -b ${basedev}1 && livedev=${basedev}1 && ps=$(partx -go START $livedev) + ;; + /dev/mmblk*) + test -b ${basedev}p1 && livedev=${basedev}p1 && ps=$(partx -go START $livedev) + ;; + esac +else + ps=$(partx -go START $livedev) +fi + +info "mgalive basedev is $basedev" +info "mgalive livedev is $livedev" +info "mgalive basedir is $basedir/" +info "mgalive overlay is $overlay" + +media=$livedev + +if [ $ps -ne 0 ] ; then + if strstr "$(blkid $basedev)" "iso9660" ; then + # This happens when we boot from a USB stick with a isohybrid partition + # scheme where the first sector is unclaimed, so the first partition starts + # at sector 1. The iso9660 filesystem starts at sector 0, so blkid doesn't + # detect a valid filesystem in the first partition. In the past, udev linked + # the entry in /dev/disk/by-label to the first partition, not to the raw + # device, and that is what we got passed in $1 (mga#3334). More recently, + # udev links it to the base device (mga#27629). The preceding tests ensure + # we handle both cases. + if [ -n "$overlay" ] ; then + # If we mount the raw device, we can't then also mount a partition + # on that device. So to enable persistence, we need to extend the + # first partition to claim the full range of the iso9660 filesystem. + # The loops waiting for udev are to ensure we don't try to mount the + # partition in the small window when udev has removed it but not yet + # re-added it (mga#27638). + pe=$(partx -go END $livedev) + if [ $ps -eq 1 ] ; then + info "Extending $livedev to cover sector 0" + delpart $basedev 1 + while [ -e $livedev ] ; do + info "Wait for udev to remove $livedev" + done + addpart $basedev 1 0 $pe + while [ ! -e $livedev ] ; do + info "Wait for udev to re-add $livedev" + done + else + info "$livedev is not a valid protective partition" + fi + else + # If we don't have a persistent partition, take the easy option. + info "Using $basedev to mount the iso9660 filesystem" + media=$basedev + fi + else + info "$basedev does not contain a valid filesystem" + fi +fi + +# Mount the live media +mount -n -o ro $media /live/media + +# Mount the loopback filesystem +LOOPDEV=$( losetup -f ) +if [ -e /live/media$basedir/loopbacks/distrib-lzma.sqfs ] ; then + # Retain support for the original draklive. Note that despite the file + # name, it uses xz compression. + losetup -r $LOOPDEV /live/media$basedir/loopbacks/distrib-lzma.sqfs +else + losetup -r $LOOPDEV /live/media$basedir/loopbacks/distrib.sqfs +fi +mount -n -t squashfs -o ro $LOOPDEV /live/distrib +mount -n -t squashfs -o ro $LOOPDEV /run/mgalive/ovlsize + +# Mount the overlay filesystem +if [ -z "$overlay" ] ; then + mount -n -t tmpfs -o mode=755 none /live/overlay +else + mount -n -o noatime $overlay /live/overlay + echo 1 > /run/mgalive/persistent +fi +# work and memory must be on same root +mkdir -m 0755 -p /live/overlay/work +mkdir -m 0755 -p /live/overlay/memory +mount -n -t overlay overlay -o lowerdir=/live/distrib,upperdir=/live/overlay/memory,workdir=/live/overlay/work,noatime /live/union + +ln -s /live/union /dev/root + +printf '/bin/mount --rbind /live/union %s\n' "$NEWROOT" > $hookdir/mount/01-$$-live.sh +printf '/bin/umount /live/union\n' >> $hookdir/mount/01-$$-live.sh + +# /live will not be visible once we pivot, so schedule its cleanup now. +# This is needed to allow a persistent overlay to be shutdown cleanly. +umount -l /live/distrib +umount -l /live/overlay +umount -l /live/media + +need_shutdown + +exit 0 diff --git a/modules.d/90mgalive/mgalive-shutdown.sh b/modules.d/90mgalive/mgalive-shutdown.sh new file mode 100755 index 00000000..b93bb068 --- /dev/null +++ b/modules.d/90mgalive/mgalive-shutdown.sh @@ -0,0 +1,11 @@ +#!/usr/bin/sh +basedev=$(cat /run/mgalive/basedev) +if [ -e /run/mgalive/installed ] || strstr "$basedev" "/dev/sr" ; then + exec < /dev/tty0 > /dev/tty0 + eject $basedev + clear + echo "It is now safe to remove the Live medium" + echo "Press <Enter> to continue..." + read -t 30 a +fi +return 0 diff --git a/modules.d/90mgalive/module-setup.sh b/modules.d/90mgalive/module-setup.sh new file mode 100755 index 00000000..260f4e8b --- /dev/null +++ b/modules.d/90mgalive/module-setup.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +check() { + # a live host-only image doesn't really make a lot of sense + [[ $hostonly ]] && return 1 + return 255 +} + +depends() { + return 0 +} + +installkernel() { + instmods squashfs loop overlay +} + +install() { + inst_multiple blkid clear eject grep losetup umount + inst_multiple addpart delpart partx + + inst_hook cmdline 30 "$moddir/mgalive-parse.sh" + inst_hook pre-udev 30 "$moddir/mgalive-genrules.sh" + inst_hook pre-shutdown 99 "$moddir/mgalive-quit-plymouth.sh" + inst_hook shutdown 99 "$moddir/mgalive-shutdown.sh" + inst "$moddir/mgalive-root.sh" "/sbin/mgalive-root" + # should probably just be generally included + inst_rules 60-cdrom_id.rules +} -- 2.13.7