#!/bin/bash # Convert a live CD iso so that it's bootable off of a USB stick # Copyright 2007 Red Hat, Inc. # Jeremy Katz # # overlay/persistence enhancements by Douglas McClendon # GPT+MBR hybrid enhancements by Stewart Adam # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; version 2 of the License. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Library General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. export PATH=/sbin:/usr/sbin:$PATH usage() { echo " $0 [--help] [--format] [--reset-mbr] [--efi] [--extra-kernel-args ] [--multi] [--livedir ] [--compress] [--skip-compress] [--swap-size-mb ] [--xo] [--xo-no-home] [--noverify] [--skipcopy] [--overlay-size-mb ] [--copy-overlay] [--delete-home] [--home-size-mb ] [--copy-home] [--crypted-home] [--unencrypted-home] --help Displays usage information and exits. --format Formats the USB stick and creates an MS-DOS partition table (or GPT partition table if --efi is passed). --reset-mbr Sets the Master Boot Record(MBR) of the USB storage device to the mbr.bin file from the image's syslinux directory. --efi Create a GPT partition table when --format is passed, and install an hybrid EFI/MBR bootloader on the disk. This is necessary for most Intel Macs. --extra-kernel-args Specifies additional kernel arguments, , that will be inserted into the syslinux and EFI boot configurations. Multiple arguments should be specified in one string, such as, --extra-kernel-args \"arg1 arg2 ...\" --multi Used when enabling multi image copies to avoid boot configuration of a particular image. --livedir Used with multi image copies to select the particular image to boot. --compress (default option to use a compressed squash filesystem) Installs image on a compressed squash filesystem. --skip-compress (default for when option --xo is specified) Installs the operation system into a ext3 filesystem image file. --xo Used to prepare an image for the OLPC XO laptop and its compressed JFFS2 filesystem. Do not use the following options with --xo: --overlay-size-mb , home-size-mb , --delete-home, --copy-home, --copy-overlay, --compress --xo-no-home Used together with the --xo option to prepare an image for an OLPC XO laptop with the home folder on an SD card instead of the internal NAND flash storage. --noverify Disables the image validation process which occurs before the image is installed. When this option is enabled the image is not verified before installation on the USB storage device. --skipcopy Skips the copy of the live image to the USB stick. (Used to repair disk configuration files or while testing the script to avoid repeated and length copy commands.) --overlay-size-mb This option specifies the creation of a persistent overlay and sets its in megabytes. The overlay is additional storage available to the live operating system if the operating system supports it. The USB storage device must have enough free space for the image and the overlay. --copy-overlay This option allows one to copy a persistent overlay from a running live image to the new installation. Changes already made in the running image will be propagated to the new installation. B User sensitive information such as password cookies and activity histories will be copied to the new installation! Scrub this information before using this option. --delete-home Must be explicitly selected when options --home-size-mb or --copy-home are selected and there is an existing persistent home directory on the image. --home-size-mb Specifies creation of a persistent home directory and sets its size in megabytes. Note that --delete-home must also be selected to replace an existing persistent home with a new, empty one. --copy-home This option allows one to copy a persistent home folder from a running live image to the new installation. Changes already made in the running image home directory will be propagated to the new installation. B User sensitive information such as password cookies and activity histories will be copied to the new installation! Scrub this information before using this option. --force This option allows one to bypass the user confirmation for deletion of an existing home directory on the target device, if one exists. --crypted-home (default, if home-size-mb is specified) Encrypts a persistent home directory. --unencrypted-home Disables the encryption of the persistent home directory." exit 1 } cleanup() { sleep 2 [ -d "$CDMNT" ] && umount $CDMNT && rmdir $CDMNT [ -d "$USBMNT" ] && umount $USBMNT && rmdir $USBMNT } exitclean() { echo "Cleaning up to exit..." cleanup exit 1 } getdisk() { DEV=$1 if [[ "$DEV" =~ "/dev/loop*" ]]; then device="$DEV" return fi p=$(udevadm info -q path -n $DEV) if [ -e /sys/$p/device ]; then device=$(basename /sys/$p) else device=$(basename $(readlink -f /sys/$p/../)) fi if [ ! -e /sys/block/$device -o ! -e /dev/$device ]; then echo "Error finding block device of $DEV. Aborting!" exitclean fi device="/dev/$device" # FIXME: weird dev names could mess this up I guess p=/dev/`basename $p` partnum=${p##$device} } resetMBR() { if [[ "$DEV" =~ "/dev/loop*" ]]; then return fi getdisk $1 # if efi, we need to use the hybrid MBR if [ -n "$efi" ];then if [ -f /usr/lib/syslinux/gptmbr.bin ]; then gptmbr='/usr/lib/syslinux/gptmbr.bin' elif [ -f /usr/share/syslinux/gptmbr.bin ]; then gptmbr='/usr/share/syslinux/gptmbr.bin' else echo "Could not find gptmbr.bin (syslinux)" exitclean fi # our magic number is LBA-2, offset 16 - (512+512+16)/$bs dd if=$device bs=16 skip=65 count=1 | cat $gptmbr - > $device else if [ -f /usr/lib/syslinux/mbr.bin ]; then cat /usr/lib/syslinux/mbr.bin > $device elif [ -f /usr/share/syslinux/mbr.bin ]; then cat /usr/share/syslinux/mbr.bin > $device else echo "Could not find mbr.bin (syslinux)" exitclean fi fi } checkMBR() { if [[ "$DEV" =~ "/dev/loop*" ]]; then return 0 fi getdisk $1 bs=$(mktemp /tmp/bs.XXXXXX) dd if=$device of=$bs bs=512 count=1 2>/dev/null || exit 2 mbrword=$(hexdump -n 2 $bs |head -n 1|awk {'print $2;'}) rm -f $bs if [ "$mbrword" = "0000" ]; then echo "MBR appears to be blank." echo "Do you want to replace the MBR on this device?" echo "Press Enter to continue or Ctrl-c to abort" read resetMBR $1 fi return 0 } checkPartActive() { dev=$1 getdisk $dev # if we're installing to whole-disk and not a partition, then we # don't need to worry about being active if [ "$dev" = "$device" ]; then return fi if [[ "$dev" =~ "/dev/loop*" ]]; then return fi if [ "$(/sbin/fdisk -l $device 2>/dev/null |grep $dev |awk {'print $2;'})" != "*" ]; then echo "Partition isn't marked bootable!" echo "You can mark the partition as bootable with " echo " # /sbin/parted $device" echo " (parted) toggle N boot" echo " (parted) quit" exitclean fi } createGPTLayout() { dev=$1 getdisk $dev echo "WARNING: THIS WILL DESTROY ANY DATA ON $device!!!" echo "Press Enter to continue or ctrl-c to abort" read umount ${device}? &> /dev/null /sbin/parted --script $device mklabel gpt partinfo=$(LC_ALL=C /sbin/parted --script -m $device "unit b print" |grep ^$device:) size=$(echo $partinfo |cut -d : -f 2 |sed -e 's/B$//') /sbin/parted --script $device unit b mkpart '"EFI System Partition"' fat32 17408 $(($size - 17408)) set 1 boot on USBDEV=${device}1 # Sometimes automount can be _really_ annoying. echo "Waiting for devices to settle..." /sbin/udevadm settle sleep 5 umount $USBDEV &> /dev/null /sbin/mkdosfs -n LIVE $USBDEV USBLABEL="UUID=$(/sbin/blkid -s UUID -o value $USBDEV)" } createMSDOSLayout() { dev=$1 getdisk $dev echo "WARNING: THIS WILL DESTROY ANY DATA ON $device!!!" echo "Press Enter to continue or Ctrl-c to abort" read umount ${device}? &> /dev/null /sbin/parted --script $device mklabel msdos partinfo=$(LC_ALL=C /sbin/parted --script -m $device "unit b print" |grep ^$device:) size=$(echo $partinfo |cut -d : -f 2 |sed -e 's/B$//') /sbin/parted --script $device unit b mkpart primary fat32 17408 $(($size - 17408)) set 1 boot on USBDEV=${device}1 # Sometimes automount can be _really_ annoying. echo "Waiting for devices to settle..." /sbin/udevadm settle sleep 5 umount $USBDEV &> /dev/null /sbin/mkdosfs -n LIVE $USBDEV USBLABEL="UUID=$(/sbin/blkid -s UUID -o value $USBDEV)" } checkGPT() { dev=$1 getdisk $dev if [ "$(/sbin/fdisk -l $device 2>/dev/null |grep -c GPT)" -eq "0" ]; then echo "EFI boot requires a GPT partition table." echo "This can be done manually or you can run with --format" exitclean fi partinfo=$(LC_ALL=C /sbin/parted --script -m $device "print" |grep ^$partnum:) volname=$(echo $partinfo |cut -d : -f 6) flags=$(echo $partinfo |cut -d : -f 7) if [ "$volname" != "EFI System Partition" ]; then echo "Partition name must be 'EFI System Partition'" echo "This can be set in parted or you can run with --reset-mbr" exitclean fi if [ "$(echo $flags |grep -c boot)" = "0" ]; then echo "Partition isn't marked bootable!" echo "You can mark the partition as bootable with " echo " # /sbin/parted $device" echo " (parted) toggle N boot" echo " (parted) quit" exitclean fi } checkFilesystem() { dev=$1 USBFS=$(/sbin/blkid -s TYPE -o value $dev) if [ "$USBFS" != "vfat" -a "$USBFS" != "msdos" -a "$USBFS" != "ext2" -a "$USBFS" != "ext3" ]; then echo "USB filesystem must be vfat or ext[23]" exitclean fi USBLABEL=$(/sbin/blkid -s UUID -o value $dev) if [ -n "$USBLABEL" ]; then USBLABEL="UUID=$USBLABEL"; else USBLABEL=$(/sbin/blkid -s LABEL -o value $dev) if [ -n "$USBLABEL" ]; then USBLABEL="LABEL=$USBLABEL" else echo "Need to have a filesystem label or UUID for your USB device" if [ "$USBFS" = "vfat" -o "$USBFS" = "msdos" ]; then echo "Label can be set with /sbin/dosfslabel" elif [ "$USBFS" = "ext2" -o "$USBFS" = "ext3" ]; then echo "Label can be set with /sbin/e2label" fi exitclean fi fi if [ "$USBFS" = "vfat" -o "$USBFS" = "msdos" ]; then mountopts="-o shortname=winnt,umask=0077" fi } checkSyslinuxVersion() { if [ ! -x /usr/bin/syslinux ]; then echo "You need to have syslinux installed to run this script" exit 1 fi if ! syslinux 2>&1 | grep -qe -d; then SYSLINUXPATH="" elif [ -n "$multi" ]; then SYSLINUXPATH="$LIVEOS/syslinux" else SYSLINUXPATH="syslinux" fi } checkMounted() { dev=$1 if grep -q "^$dev " /proc/mounts ; then echo "$dev is mounted, please unmount for safety" exitclean fi if grep -q "^$dev " /proc/swaps; then echo "$dev is in use as a swap device, please disable swap" exitclean fi } checkint() { if ! test $1 -gt 0 2>/dev/null ; then echo "ERROR: You must specify a $1 value." usage fi } detectisotype() { if [ -e $CDMNT/LiveOS/squashfs.img ]; then isotype=live return fi if [ -e $CDMNT/images/install.img ]; then isotype=installer return fi echo "ERROR: $ISO does not appear to be a Live image or DVD installer." exitclean } cryptedhome=1 keephome=1 homesizemb=0 copyhomesize=0 swapsizemb=0 overlaysizemb=0 copyoverlaysize=0 isotype= LIVEOS=LiveOS HOMEFILE="home.img" while [ $# -gt 2 ]; do case $1 in --help) usage ;; --format) format=1 ;; --reset-mbr|--resetmbr) resetmbr=1 ;; --efi|--mactel) efi=1 ;; --extra-kernel-args) kernelargs=$2 shift ;; --multi) multi=1 ;; --livedir) LIVEOS=$2 shift ;; --compress) skipcompress="" ;; --skipcompress) skipcompress=1 ;; --swap-size-mb) checkint $2 swapsizemb=$2 shift ;; --xo) xo=1 skipcompress=1 ;; --xo-no-home) xonohome=1 ;; --noverify) noverify=1 ;; --skipcopy) skipcopy=1 ;; --overlay-size-mb) checkint $2 overlaysizemb=$2 shift ;; --copy-overlay) copyoverlay=1 ;; --delete-home) keephome="" ;; --home-size-mb) checkint $2 homesizemb=$2 shift ;; --copy-home) copyhome=1 ;; --force) force=1 ;; --crypted-home) cryptedhome=1 ;; --unencrypted-home) cryptedhome="" ;; *) echo "invalid arg -- $1" usage ;; esac shift done ISO=$(readlink -f "$1") USBDEV=$(readlink -f "$2") if [ -z "$ISO" ]; then echo "ERROR: You haven't specified a source image in \ Please adjust this command requirement." usage fi if [ ! -b "$ISO" -a ! -f "$ISO" ]; then echo "$(ISO) is not a valid source image.\ Please adjust this command requirement." usage fi # FIXME: If --format is given, we shouldn't care and just use /dev/foo1 if [ -z "$USBDEV" -o ! -b "$USBDEV" ]; then usage fi if [ $(id -u) != 0 ]; then echo "You need to be root to run this script" exit 1 fi # do some basic sanity checks. checkMounted $USBDEV if [ -n "$format" ];then # checks for a valid filesystem if [ -n "$efi" ];then createGPTLayout $USBDEV else createMSDOSLayout $USBDEV fi fi checkFilesystem $USBDEV if [ -n "$efi" ]; then checkGPT $USBDEV fi checkSyslinuxVersion # Because we can't set boot flag for EFI Protective on msdos partition tables [ -z "$efi" ] && checkPartActive $USBDEV [ -n "$resetmbr" ] && resetMBR $USBDEV checkMBR $USBDEV if [ "$ISO" = "$USBDEV" ]; then echo "Source and destination images are on the same device partition." echo "Please check your inputs." exitclean fi if [ "$overlaysizemb" -gt 0 -a "$USBFS" = "vfat" ]; then if [ "$overlaysizemb" -gt 2047 ]; then echo "Can't have an overlay of 2048 MB or greater on VFAT" exitclean fi fi if [ "$homesizemb" -gt 0 -a "$USBFS" = "vfat" ]; then if [ "$homesizemb" -gt 2047 ]; then echo "Can't have a home overlay greater than 2048 MB on VFAT" exitclean fi fi if [ "$swapsizemb" -gt 0 -a "$USBFS" = "vfat" ]; then if [ "$swapsizemb" -gt 2047 ]; then echo "Can't have a swap file greater than 2048 MB on VFAT" exitclean fi fi # FIXME: would be better if we had better mountpoints CDMNT=$(mktemp -d /media/cdtmp.XXXXXX) mount -o loop,ro "$ISO" $CDMNT || exitclean USBMNT=$(mktemp -d /media/usbdev.XXXXXX) mount $mountopts $USBDEV $USBMNT || exitclean trap exitclean SIGINT SIGTERM detectisotype if [ -f "$USBMNT/$LIVEOS/$HOMEFILE" -a -n "$keephome" -a "$homesizemb" -gt 0 ]; then echo "ERROR: Your target has an existing /home and you requested both keeping it and specified a size for a new /home. To remove an exiting /home, you must specify --delete-home explicitly. Please adjust your home options." cleanup usage fi if [ -f "$USBMNT/$LIVEOS/$HOMEFILE" -a -n "$keephome" -a -n "$copyhome" -a -s "$CDMNT/$LIVEOS/$HOMEFILE" ]; then echo "ERROR: Your target has an existing /home and you requested both keeping it and copying one from the source. To remove an exiting /home, you must specify --delete-home explicitly. Please adjust your home options." cleanup usage fi if [ -z "$noverify" ]; then # verify the image echo "Verifying image..." checkisomd5 --verbose "$ISO" if [ $? -ne 0 ]; then echo "Are you SURE you want to continue? Press Enter to continue or Ctrl-c to abort" read fi fi SOURCEOVERLAY="overlay-$( /sbin/blkid -s LABEL -o value $ISO )-$( /sbin/blkid -s UUID -o value $ISO )" if [ -f "$CDMNT/$LIVEOS/$SOURCEOVERLAY" -a -n "$copyoverlay" -a "$overlaysizemb" -gt 0 ]; then echo "ERROR: You requested both a new overlay and copying one from the source. Please request only one of these options." cleanup usage fi if [ -f "$CDMNT/$LIVEOS/$HOMEFILE" -a -n "copyhome" -a "$homesizemb" -gt 0 ]; then echo "ERROR: You requested both a new home and copying one from the source. Please request only one of these options." cleanup usage fi if [ -n "$efi" -a ! -d $CDMNT/EFI/boot ]; then echo "ERROR: This live image does not support EFI booting" exitclean fi # let's try to make sure there's enough room on the stick if [ -d $CDMNT/LiveOS ]; then check=$CDMNT/LiveOS else check=$CDMNT fi if [ -d $USBMNT/$LIVEOS ]; then tbd=$(du -s -B 1M $USBMNT/$LIVEOS | awk {'print $1;'}) [ -f $USBMNT/$LIVEOS/$HOMEFILE ] && homesz=$(du -s -B 1M $USBMNT/$LIVEOS/$HOMEFILE | awk {'print $1;'}) [ -n "$homesz" -a -n "$keephome" ] && tbd=$(($tbd - $homesz)) else tbd=0 fi livesize=$(du -s -B 1M $check | awk {'print $1;'}) if [ -z "$copyoverlay" ]; then if [ -s $check/$SOURCEOVERLAY ]; then copyoverlaysize=$(du -s -B 1M $check/$SOURCEOVERLAY | awk {'print $1;'}) livesize=$(($livesize - $copyoverlaysize)) fi elif [ ! -s $check/$SOURCEOVERLAY ]; then echo "There appears to be no persistent overlay file on this image. Are you SURE you want to continue? Press Enter to continue or Ctrl-c to abort." read fi if [ -z "$copyhome" ]; then if [ -s $check/$HOMEFILE ]; then copyhomesize=$(du -s -B 1M $check/$HOMEFILE | awk {'print $1;'}) livesize=$(($livesize - $copyhomesize)) fi elif [ ! -s $check/$HOMEFILE ]; then echo "There appears to be no persistent /home file on this image. Are you SURE you want to continue? Press Enter to continue or Ctrl-c to abort." read fi if [ -n "$skipcompress" ]; then if [ -e $CDMNT/LiveOS/squashfs.img ]; then if mount -o loop $CDMNT/LiveOS/squashfs.img $CDMNT; then livesize=$(du -s -B 1M $CDMNT/LiveOS/ext3fs.img | awk {'print $1;'}) umount $CDMNT else echo "WARNING: --skipcompress or --xo was specified but the currently running kernel can not mount the squashfs from the ISO file to extract it. The compressed squashfs will be copied to the USB stick." skipcompress="" fi fi fi free=$(df -B1M $USBDEV |tail -n 1 |awk {'print $4;'}) if [ "$isotype" = "live" ]; then tba=$(($overlaysizemb + $copyoverlaysize + $homesizemb + $copyhomesize + $livesize + $swapsizemb)) if [ $tba -gt $(($free + $tbd)) ]; then echo "Unable to fit live image + overlay on available space on USB stick + Size of live image: $livesize" [ "$overlaysizemb" -gt 0 ] && echo "+ Overlay size: $overlaysizemb" [ "$copyoverlaysize" -gt 0 ] && echo "+ Copy overlay size: $copyoverlaysize" [ "$homesizemb" -gt 0 ] && echo "+ Home overlay size: $homesizemb" [ "$copyhomesize" -gt 0 ] && echo "+ Copy home overlay size: $copyhomesize" [ "$swapsizemb" -gt 0 ] && echo "+ Swap overlay size: $swapsizemb" echo "--------------------------- = Requested: $tba - Available: $(($free + $tbd)) --------------------------- = To fit, free or decrease requested size total by: $(($tba - $free - $tbd))" exitclean fi fi # Verify available space for DVD installer if [ "$isotype" = "installer" ]; then isosize=$(du -s -B 1M $ISO | awk {'print $1;'}) installimgsize=$(du -s -B 1M $CDMNT/images/install.img | awk {'print $1;'}) tbd=0 if [ -e $USBMNT/images/install.img ]; then tbd=$(du -s -B 1M $USBMNT/images/install.img | awk {'print $1;'}) fi if [ -e $USBMNT/$(basename $ISO) ]; then tbd=$(($tbd + $(du -s -B 1M $USBMNT/$(basename $ISO) | awk {'print $1;'}))) fi echo "Size of DVD image: $isosize Size of install.img: $installimgsize Available space: $(($free + $tbd))" if [ $(($isosize + $installimgsize)) -gt $(($free + $tbd)) ]; then echo "ERROR: Unable to fit DVD image + install.img on available space on USB stick" exitclean fi fi if [ -z "$skipcopy" ] && [ "$isotype" = "live" ]; then if [ -d $USBMNT/$LIVEOS -a -z "$force" ]; then echo "Already set up as live image." if [ -z "$keephome" -a -e $USBMNT/$LIVEOS/$HOMEFILE ]; then echo "WARNING: The old persistent /home will be deleted!!! Press Enter to continue or Ctrl-c to abort" read else echo "Deleting old OS in fifteen seconds..." sleep 15 [ -e "$USBMNT/$LIVEOS/$HOMEFILE" -a -n "$keephome" ] && mv $USBMNT/$LIVEOS/$HOMEFILE $USBMNT/$HOMEFILE fi rm -rf $USBMNT/$LIVEOS fi fi # Bootloader is always reconfigured, so keep these out of the if skipcopy stuff. [ ! -d $USBMNT/$SYSLINUXPATH ] && mkdir -p $USBMNT/$SYSLINUXPATH [ -n "$efi" -a ! -d $USBMNT/EFI/boot ] && mkdir -p $USBMNT/EFI/boot # Live image copy if [ -z "$skipcopy" ] && [ "$isotype" = "live" ]; then echo "Copying live image to USB stick" [ ! -d $USBMNT/$LIVEOS ] && mkdir $USBMNT/$LIVEOS [ -n "$keephome" -a -f "$USBMNT/$HOMEFILE" ] && mv $USBMNT/$HOMEFILE $USBMNT/$LIVEOS/$HOMEFILE if [ -n "$skipcompress" -a -f $CDMNT/LiveOS/squashfs.img ]; then mount -o loop $CDMNT/LiveOS/squashfs.img $CDMNT || exitclean cp $CDMNT/LiveOS/ext3fs.img $USBMNT/$LIVEOS/ext3fs.img || (umount $CDMNT ; exitclean) umount $CDMNT elif [ -f $CDMNT/LiveOS/squashfs.img ]; then cp $CDMNT/LiveOS/squashfs.img $USBMNT/$LIVEOS/squashfs.img || exitclean elif [ -f $CDMNT/LiveOS/ext3fs.img ]; then cp $CDMNT/LiveOS/ext3fs.img $USBMNT/$LIVEOS/ext3fs.img || exitclean fi if [ -f $CDMNT/LiveOS/osmin.img ]; then cp $CDMNT/LiveOS/osmin.img $USBMNT/$LIVEOS/osmin.img || exitclean fi if [ -n "$copyoverlay" ]; then SOURCEOVERLAY="overlay-$( /sbin/blkid -s LABEL -o value $ISO )-$( /sbin/blkid -s UUID -o value $ISO )" cp $CDMNT/$LIVEOS/$SOURCEOVERLAY $USBMNT/$LIVEOS/$SOURCEOVERLAY || exitclean fi [ -f $CDMNT/$LIVEOS/$HOMEFILE -a -n "$copyhome" ] && ( cp $CDMNT/$LIVEOS/$HOMEFILE $USBMNT/$LIVEOS/$HOMEFILE || exitclean ) # copy this installer script to enable the new installation to replicate the image THISSCRIPT=$(readlink -f $0) cp -f $THISSCRIPT $USBMNT/modified_livecd-iso-to-disk fi # DVD installer copy if [ -z "$skipcopy" ] && [ "$isotype" = "installer" ]; then echo "Copying DVD image to USB stick" mkdir -p $USBMNT/images/ cp $CDMNT/images/install.img $USBMNT/images/install.img || exitclean cp $ISO $USBMNT/ fi # adjust syslinux sources for replication of installed images between filesystem types if [ -d $CDMNT/isolinux/ ]; then cp $CDMNT/isolinux/* $USBMNT/$SYSLINUXPATH elif [ -d $CDMNT/syslinux/ ]; then cp $CDMNT/syslinux/* $USBMNT/$SYSLINUXPATH if [ -f $CDMNT/syslinux/extlinux.conf ]; then mv $USBMNT/$SYSLINUXPATH/extlinux.conf $USBMNT/$SYSLINUXPATH/isolinux.cfg elif [ -f $CDMNT/syslinux/syslinux.cfg ]; then mv $USBMNT/$SYSLINUXPATH/syslinux.cfg $USBMNT/$SYSLINUXPATH/isolinux.cfg fi fi BOOTCONFIG=$USBMNT/$SYSLINUXPATH/isolinux.cfg # Set this to nothing so sed doesn't care BOOTCONFIG_EFI= if [ -n "$efi" ];then cp $CDMNT/EFI/boot/* $USBMNT/EFI/boot # this is a little ugly, but it gets the "interesting" named config file BOOTCONFIG_EFI=$USBMNT/EFI/boot/boot?*.conf rm -f $USBMNT/EFI/boot/grub.conf fi # restore boot config file to base state before updating sed -i -e "s/root=[^ ]*/root=CDLABEL=name/" -e "s/liveimg .* quiet/liveimg quiet/" $BOOTCONFIG $BOOTCONFIG_EFI echo "Updating boot config file" # adjust label and fstype sed -i -e "s/CDLABEL=[^ ]*/$USBLABEL/" -e "s/rootfstype=[^ ]*/rootfstype=$USBFS/" -e "s/LABEL=[^ ]*/$USBLABEL/" $BOOTCONFIG $BOOTCONFIG_EFI if [ -n "$kernelargs" ]; then sed -i -e "s/liveimg/liveimg ${kernelargs}/" $BOOTCONFIG $BOOTCONFIG_EFI fi if [ "$LIVEOS" != "LiveOS" ]; then sed -i -e "s;liveimg;liveimg live_dir=$LIVEOS;" $BOOTCONFIG $BOOTCONFIG_EFI fi # DVD Installer if [ "$isotype" = "installer" ]; then sed -i -e "s;initrd=initrd.img;initrd=initrd.img repo=hd:$USBLABEL:/;g" $BOOTCONFIG $BOOTCONFIG_EFI sed -i -e "s;stage2=\S*;;g" $BOOTCONFIG $BOOTCONFIG_EFI fi if [ "$overlaysizemb" -gt 0 ]; then echo "Initializing persistent overlay file" OVERFILE="overlay-$( /sbin/blkid -s LABEL -o value $USBDEV )-$( /sbin/blkid -s UUID -o value $USBDEV )" if [ "$USBFS" = "vfat" ]; then # vfat can't handle sparse files dd if=/dev/zero of=$USBMNT/$LIVEOS/$OVERFILE count=$overlaysizemb bs=1M else dd if=/dev/null of=$USBMNT/$LIVEOS/$OVERFILE count=1 bs=1M seek=$overlaysizemb fi sed -i -e "s/liveimg/liveimg overlay=${USBLABEL}/" $BOOTCONFIG $BOOTCONFIG_EFI sed -i -e "s/\ ro\ /\ rw\ /" $BOOTCONFIG $BOOTCONFIG_EFI elif [ -n "$copyoverlay" ]; then OVERFILE="overlay-$( /sbin/blkid -s LABEL -o value $USBDEV )-$( /sbin/blkid -s UUID -o value $USBDEV )" mv $USBMNT/$LIVEOS/$SOURCEOVERLAY $USBMNT/$LIVEOS/$OVERFILE sed -i -e "s/liveimg/liveimg overlay=${USBLABEL}/" $BOOTCONFIG $BOOTCONFIG_EFI sed -i -e "s/\ ro\ /\ rw\ /" $BOOTCONFIG $BOOTCONFIG_EFI fi if [ "$swapsizemb" -gt 0 ]; then echo "Initializing swap file" dd if=/dev/zero of=$USBMNT/$LIVEOS/swap.img count=$swapsizemb bs=1M mkswap -f $USBMNT/$LIVEOS/swap.img fi if [ "$homesizemb" -gt 0 ]; then echo "Initializing persistent /home" homesource=/dev/zero [ -n "$cryptedhome" ] && homesource=/dev/urandom if [ "$USBFS" = "vfat" ]; then # vfat can't handle sparse files dd if=${homesource} of=$USBMNT/$LIVEOS/$HOMEFILE count=$homesizemb bs=1M else dd if=/dev/null of=$USBMNT/$LIVEOS/$HOMEFILE count=1 bs=1M seek=$homesizemb fi if [ -n "$cryptedhome" ]; then loop=$(losetup -f) losetup $loop $USBMNT/$LIVEOS/$HOMEFILE setupworked=1 until [ ${setupworked} == 0 ]; do echo "Encrypting persistent /home" cryptsetup luksFormat -y -q $loop setupworked=$? done setupworked=1 until [ ${setupworked} == 0 ]; do echo "Please enter the password again to unlock the device" cryptsetup luksOpen $loop EncHomeFoo setupworked=$? done mke2fs -j /dev/mapper/EncHomeFoo tune2fs -c0 -i0 -ouser_xattr,acl /dev/mapper/EncHomeFoo sleep 2 cryptsetup luksClose EncHomeFoo losetup -d $loop else echo "Formatting unencrypted /home" mke2fs -F -j $USBMNT/$LIVEOS/$HOMEFILE tune2fs -c0 -i0 -ouser_xattr,acl $USBMNT/$LIVEOS/$HOMEFILE fi fi # create the forth files for booting on the XO if requested # we'd do this unconditionally, but you have to have a kernel that will # boot on the XO anyway. if [ -n "$xo" ]; then echo "Setting up /boot/olpc.fth file" args=$(egrep "^[ ]*append" $USBMNT/$SYSLINUXPATH/isolinux.cfg |head -n1 |sed -e 's/.*initrd=[^ ]*//') if [ -z "$xonohome" -a ! -f $USBMNT/$LIVEOS/$HOMEFILE ]; then args="$args persistenthome=mtd0" fi args="$args reset_overlay" xosyspath=$(echo $SYSLINUXPATH | sed -e 's;/;\\;') if [ ! -d $USBMNT/boot ]; then mkdir -p $USBMNT/boot fi cat > $USBMNT/boot/olpc.fth <= if " sd:" else " u:" then " BOOTPATHDEV" \$set-macro ; set-bootpath-dev " $args" to boot-file " \${BOOTPATHDEV}$xosyspath\initrd0.img" expand$ to ramdisk " \${BOOTPATHDEV}$xosyspath\vmlinuz0" expand$ to boot-device unfreeze boot EOF fi if [ -z "$multi" ]; then echo "Installing boot loader" if [ -n "$efi" ]; then # replace the ia32 hack if [ -f "$USBMNT/EFI/boot/boot.conf" ]; then cp -f $USBMNT/EFI/boot/bootia32.conf $USBMNT/EFI/boot/boot.conf fi fi # this is a bit of a kludge, but syslinux doesn't guarantee the API for its com32 modules :/ if [ -f $USBMNT/$SYSLINUXPATH/vesamenu.c32 -a -f /usr/share/syslinux/vesamenu.c32 ]; then cp /usr/share/syslinux/vesamenu.c32 $USBMNT/$SYSLINUXPATH/vesamenu.c32 elif [ -f $USBMNT/$SYSLINUXPATH/vesamenu.c32 -a -f /usr/lib/syslinux/vesamenu.c32 ]; then cp /usr/lib/syslinux/vesamenu.c32 $USBMNT/$SYSLINUXPATH/vesamenu.c32 elif [ -f $USBMNT/$SYSLINUXPATH/menu.c32 -a -f /usr/share/syslinux/menu.c32 ]; then cp /usr/share/syslinux/menu.c32 $USBMNT/$SYSLINUXPATH/menu.c32 elif [ -f $USBMNT/$SYSLINUXPATH/menu.c32 -a -f /usr/lib/syslinux/menu.c32 ]; then cp /usr/lib/syslinux/menu.c32 $USBMNT/$SYSLINUXPATH/menu.c32 fi if [ "$USBFS" = "vfat" -o "$USBFS" = "msdos" ]; then # syslinux expects the config to be named syslinux.cfg # and has to run with the file system unmounted mv $USBMNT/$SYSLINUXPATH/isolinux.cfg $USBMNT/$SYSLINUXPATH/syslinux.cfg # deal with mtools complaining about ldlinux.sys if [ -f $USBMNT/$SYSLINUXPATH/ldlinux.sys ]; then rm -f $USBMNT/$SYSLINUXPATH/ldlinux.sys fi cleanup if [ -n "$SYSLINUXPATH" ]; then syslinux -d $SYSLINUXPATH $USBDEV else syslinux $USBDEV fi elif [ "$USBFS" = "ext2" -o "$USBFS" = "ext3" ]; then # extlinux expects the config to be named extlinux.conf # and has to be run with the file system mounted mv $USBMNT/$SYSLINUXPATH/isolinux.cfg $USBMNT/$SYSLINUXPATH/extlinux.conf extlinux -i $USBMNT/$SYSLINUXPATH chattr -i $USBMNT/$SYSLINUXPATH/extlinux.sys cleanup fi else # we need to do some more config file tweaks for multi-image mode sed -i -e "s;kernel vm;kernel /$LIVEOS/syslinux/vm;" $USBMNT/$SYSLINUXPATH/isolinux.cfg sed -i -e "s;initrd=i;initrd=/$LIVEOS/syslinux/i;" $USBMNT/$SYSLINUXPATH/isolinux.cfg mv $USBMNT/$SYSLINUXPATH/isolinux.cfg $USBMNT/$SYSLINUXPATH/syslinux.cfg cleanup fi echo "USB stick set up as live image!"