#!/bin/bash

# mayflower - flexible mkinitrd replacement
#
# Copyright 2006 David Zeuthen <davidz@redhat.com>
#
# Licensed under the GPLv2. See the file COPYING for details. 
# Inspired by similar programs from a bunch of other distributions.
#

usage() {
    echo "$0 [--help] <out-initrd-image> <kernel-version>"
    echo
    echo "example: $0 /boot/myinitramfs.img \`uname -r\`"
}

opt_allow_overwrite=0
opt_verbose=0
INITRAMFS_TARGET=""
KERNEL=""
while [ $# -gt 0 ] ; do
    case $1 in
        --help)
            usage
            exit 0
            ;;
        -f)
            opt_allow_overwrite=1
            ;;
        --allow-missing)
	    echo "Ignore option $1 for /sbin/mkinitrd compatibility"
	    ;;
        -v|--verbose)
            opt_verbose=1
            ;;
        *)
            if [ -z "$INITRAMFS_TARGET" ] ; then
                INITRAMFS_TARGET=$1
            elif [ -z "$KERNEL" ] ; then
                KERNEL=$1
            else
                echo "Unknown option or parameter \"$1\""
                echo
                usage
                exit 1
            fi
            ;;
        *)
            ;;
    esac

    shift
done

if [ -z "$INITRAMFS_TARGET" -o -z "$KERNEL" ] ; then
    usage
    exit 1
fi

if [  "$opt_allow_overwrite" == "0" ] ; then
    if [ -e $INITRAMFS_TARGET ] ; then
	echo "Image $INITRAMFS_TARGET already exists. Use -f to overwrite"
	exit 1
    fi
fi

echo "Building an initramfs at $INITRAMFS_TARGET for kernel $KERNEL"

TEMPDIR=`mktemp -d` || exit 1
pushd $TEMPDIR > /dev/null
mkdir initramfs_dir
cd initramfs_dir

# Make directory structure 
mkdir bin sbin dev sys proc lib lib/udev sysroot etc etc/udev etc/udev/rules.d

cp /sbin/losetup sbin
cp /sbin/blockdev sbin
cp /sbin/dmsetup sbin
cp /bin/dd bin
cp /bin/cut bin

# we explicitly load these, so should be sure they're present
MODULES="loop dm_snapshot "

if [ -e /etc/mayflower.conf ] ; then
    source /etc/mayflower.conf
fi

# TODO: right now we only recognize MODULES... add support for more
# options such as 'include all modules neccessary to mount the mount
# point /mnt/temp_os_install' etc.

MODULES+=" "

if [ "$opt_verbose" == "1" ] ; then
    echo "Kernel modules requested: $MODULES"
    echo
fi
rm -f modules

for m in $MODULES ; do
    char=$(echo $m | cut -c1)
    if [ $char = '=' ]; then
	NAME=$(echo $m | cut -c2-)
	if [ "$NAME" = "ata" ]; then
	    if [ -f /lib/modules/$KERNEL/modules.libata ]; then
		MODS="$MODS $(cat /lib/modules/$KERNEL/modules.libata |sed -e 's/.ko//')"
	    else
		MODS="$MODS $(cat /lib/modules/$KERNEL/modules.block |egrep '(ata|ahci)' |sed -e 's/.ko//')"
	    fi
	else
	    MODS="$MODS $(cat /lib/modules/$KERNEL/modules.$NAME |sed -e 's/.ko//')"
	fi
    else
	MODS="$MODS $m"
    fi
done

for m in $MODS ; do
    /sbin/modprobe --set-version $KERNEL --show-depends $m >> modules 2>/dev/null
done

cat modules | awk '{ print $2 }' | sort -u > modules2
rm -f modules
MODULES_FILES=`cat modules2`
rm -f modules2

mkdir -p lib/modules/$KERNEL/

# Copy kernel modules over
for f in $MODULES_FILES ; do
    if [ "$opt_verbose" == "1" ] ; then
	echo "Copying kernel module $f"
    fi
    cp $f lib/modules/$KERNEL/
done

# Build module deps file so we can use modprobe
if [ "$opt_verbose" == "1" ] ; then
    /sbin/depmod -b `pwd` -v $KERNEL
else
    /sbin/depmod -b `pwd` -v $KERNEL > /dev/null
fi

# Copy /etc/fstab over
cp /etc/fstab etc

# Copy modprobe.conf and friends over
if [ -e /etc/modprobe.conf ] ; then
    cp /etc/modprobe.conf etc
fi
cp -R /etc/modprobe.d etc

# Copy binaries over
cp /bin/echo bin
cp /bin/sleep bin
cp /bin/bash bin
cp /bin/mount bin
cp /bin/umount bin
[ -x /usr/sbin/eject ] && cp /usr/sbin/eject sbin
cp /bin/ls bin
cp /bin/mknod bin
cp /bin/mkdir bin
cp /bin/chmod bin
cp /bin/ln bin
cp /bin/cat bin
cp /usr/bin/kill bin
cp /bin/rm bin

cp /sbin/udevsettle sbin
cp /sbin/udevtrigger sbin
cp /sbin/udevd sbin
cp /sbin/insmod sbin
cp /sbin/modprobe sbin
cp /sbin/pidof sbin
cp /sbin/killall5 sbin
cp /sbin/nash sbin

cp /lib/udev/vol_id lib/udev

# symlink niceties
ln -s bash bin/sh

# Not really required but nice
[ -x /usr/bin/tree ] && cp /usr/bin/tree bin
[ -x /usr/bin/less ] && cp /usr/bin/less bin
cp /bin/env bin
cp /bin/grep bin
cp /bin/dmesg bin
cp /sbin/lsmod sbin

# if we have the iso checker, we want it
[ -x /usr/lib/anaconda-runtime/checkisomd5 ] && cp /usr/lib/anaconda-runtime/checkisomd5 bin
[ -x /usr/bin/checkisomd5 ] && cp /usr/bin/checkisomd5 bin

# Copy all required shared libs
for i in bin/* sbin/* lib/udev/*; do 
    ldd $i | sed 's|.*=>||g' | awk '/\// { print $1 }' | while read lib ; do
        if [ "$opt_verbose" == "1" ] ; then
	    echo "Copying DSO $l"
        fi
        cp --parents $lib .
    done
done

cat > sbin/run-init <<EOF
#!/sbin/nash
setuproot
switchroot
EOF
chmod 755 sbin/run-init

# Write out init
cat > init <<EOF
#!/bin/bash

emergency_shell()
{
    echo "Bug in initramfs /init detected. Dropping to a shell. Good luck!"
    echo
    bash
}
trap "emergency_shell" 0 2

# exit immediately if a command fails
set -e

export PATH=/sbin:/bin

exec < /dev/console > /dev/console 2>&1

mount -n -t tmpfs -o mode=0755 udev /dev
mknod /dev/console c 5 1
mknod /dev/null c 1 3
mknod /dev/kmsg c 1 11
mkdir /dev/pts
mkdir -m 1777 /dev/shm
ln -s /proc/self/fd /dev/fd
ln -s fd/0 /dev/stdin
ln -s fd/1 /dev/stdout
ln -s fd/2 /dev/stderr

mount -n -t proc proc /proc
mount -n -t sysfs sysfs /sys

echo "" > /proc/sys/kernel/hotplug

# Declare all variables here.. mostly for housekeeping
#
init="/sbin/init"
root_ro=0
root_rw=0
root=""
rootflags=""
rootfstype=""
quiet=0
shell=0
eshell=0
live_ram=0
check_iso=0
live_locale=""

# Parse kernel commandline options
#
for o in \`cat /proc/cmdline\` ; do
    case \$o in 
    init=*)
        init=\${o#init=}
        ;;
    ro)
        root_ro=1
        ;;
    rw)
        root_rw=1
        ;;
    quiet)
        quiet=1
        ;;
    shell)
        shell=1
        ;;
    eshell)
        eshell=1
        ;;
    live_ram)
        live_ram=1
        ;;
    live_locale=*)
        live_locale=\${o#live_locale=}
        ;;
    check)
        check_iso=1
        ;;
    blacklist=*)
        blacklist=\${o#blacklist=}
        echo "blacklist \$blacklist" >> /etc/modprobe.conf
        ;;
    *)
        m=\$(echo \$o |cut -s -d . -f 1)
        opt=\$(echo \$o |cut -s -d . -f 2-)
        if [ -z "\$m" -o -z "\$opt" ]; then
          continue
        fi
        p=\$(echo \$opt |cut -s -d = -f 1)
        v=\$(echo \$opt |cut -s -d = -f 2-)
        if [ -z "\$p" -o -z "\$v" ]; then
          continue
        fi
        echo "options \$m \$p=\$v" >> /etc/modprobe.conf
        ;;
    esac
done

if [ "\$quiet" != "1" ] ; then
    echo "kernel commandline: \`cat /proc/cmdline\`"
fi

# First, read rootfs target from embedded /etc/fstab file
#
if [ -f /etc/fstab ] ; then
    root=$(cat /etc/fstab | while read d m f o r; do if [ "$m" == "/" ] ; then echo $d; fi; done)
    rootflags=$(cat /etc/fstab | while read d m f o r; do if [ "$m" == "/" ] ; then echo $o; fi; done)
    rootfstype=$(cat /etc/fstab | while read d m f o r; do if [ "$m" == "/" ] ; then echo $f; fi; done)
    if [ "\$quiet" != "1" ] ; then
        echo "fstab suggests root=\$root"
        echo "fstab suggests rootflags=\$rootflags"
        echo "fstab suggests rootfstype=\$rootfstype"
        # Handle the case with bogus /etc/fstab pointing to /dev/root
        # which by definition does not exist...
        #
        if [ "\$root" == "/dev/root" ] ; then
            echo "WARNING: Bogus /etc/fstab file - cannot have /dev/root as the device for /"
            root=""
            rootflags=""
            rootfstype=""
        fi
    fi
fi

# Users can override rootfs target on the kernel commandline
#
for o in \`cat /proc/cmdline\` ; do
    case \$o in 
    root=*)
        root=\${o#root=}
        ;;
    rootflags=*)
        rootflags=\${o#rootflags=}
        ;;
    rootfstype=*)
        rootfstype=\${o#rootfstype=}
        ;;
    esac
done

# Print out what we are going to do
#
if [ "\$quiet" != "1" ] ; then
    echo "init=\$init"
    echo "root=\$root"
    echo "rootflags=\$rootflags"
    echo "rootfstype=\$rootfstype"
    echo "root_ro=\$root_ro"
    echo "root_rw=\$root_rw"
fi

waitforsymlink=0
# generate udev rules to generate /dev/root symlink
if [ -z \$root ] ; then
    root=/dev/something
else
    case \$root in
        /dev/disk/by-label/*)
            LABEL=\${root#/dev/disk/by-label/}
            echo "SUBSYSTEM==\"block\", PROGRAM=\"/lib/udev/vol_id -l %N\", RESULT==\"\$LABEL\", SYMLINK+=\"root\"" > /etc/udev/rules.d/00-label.rules
            if [ "\$quiet" != "1" ] ; then
                echo "Added udev rule 00-label.rules:"
                cat /etc/udev/rules.d/00-label.rules
            fi
            waitforsymlink=1
            thingtomount=/dev/root
            ;;
        CDLABEL=*)
            CDLABEL=\${root#CDLABEL=}
            echo "KERNEL==\"hd[a-z]\", BUS==\"ide\", SYSFS{removable}==\"1\", ATTRS{media}==\"cdrom\", PROGRAM=\"/lib/udev/vol_id -l %N\", RESULT==\"\$CDLABEL\", SYMLINK+=\"root\"" > /etc/udev/rules.d/00-cdlabel.rules
            echo "KERNEL==\"sr[0-9]\", PROGRAM=\"/lib/udev/vol_id -l %N\", RESULT==\"\$CDLABEL\", SYMLINK+=\"root\"" >> /etc/udev/rules.d/00-cdlabel.rules
            echo "KERNEL==\"scd[0-9]\", PROGRAM=\"/lib/udev/vol_id -l %N\", RESULT==\"\$CDLABEL\", SYMLINK+=\"root\"" >> /etc/udev/rules.d/00-cdlabel.rules
            echo "KERNEL==\"pcd[0-9]\", PROGRAM=\"/lib/udev/vol_id -l %N\", RESULT==\"\$CDLABEL\", SYMLINK+=\"root\"" >> /etc/udev/rules.d/00-cdlabel.rules
            if [ "\$quiet" != "1" ] ; then
                echo "Added udev rule 00-cdlabel.rules:"
                cat /etc/udev/rules.d/00-cdlabel.rules
            fi
            waitforsymlink=1
            thingtomount=/dev/root
            ;;
        LABEL=*)
            LABEL=\${root#LABEL=}
            echo "SUBSYSTEM==\"block\", PROGRAM=\"/lib/udev/vol_id -l %N\", RESULT==\"\$LABEL\", SYMLINK+=\"root\"" > /etc/udev/rules.d/00-label.rules
            if [ "\$quiet" != "1" ] ; then
                echo "Added udev rule 00-label.rules:"
                cat /etc/udev/rules.d/00-label.rules
            fi
            waitforsymlink=1
            thingtomount=/dev/root
            ;;
        /dev/disk/by-id/*)
            UUID=\${root#/dev/disk/by-id/}
            echo "SUBSYSTEM==\"block\", PROGRAM=\"/lib/udev/vol_id -u %N\", RESULT==\"\$UUID\", SYMLINK+=\"root\"" > /etc/udev/rules.d/01-uuid.rules
            if [ "\$quiet" != "1" ] ; then
                echo "Added udev rule 01-uuid.rules:"
                cat /etc/udev/rules.d/01-uuid.rules
            fi
            waitforsymlink=1
            thingtomount=/dev/root
            ;;
        UUID=*)
            UUID=\${root#UUID=}
            echo "SUBSYSTEM==\"block\", PROGRAM=\"/lib/udev/vol_id -u %N\", RESULT==\"\$UUID\", SYMLINK+=\"root\"" > /etc/udev/rules.d/01-uuid.rules
            if [ "\$quiet" != "1" ] ; then
                echo "Added udev rule 01-uuid.rules:"
                cat /etc/udev/rules.d/01-uuid.rules
            fi
            waitforsymlink=1
            thingtomount=/dev/root
            ;;
        /dev/*)
            ln -s \$root /dev/root
            thingtomount=\$root
            ;;
        *)
            thingtomount=\$root      
            ;;
    esac
fi

echo "udev_log=\"error\"" >> /etc/udev/udev.conf

# rules for loading modules
#
echo -n "ACTION==\"add\", SUBSYSTEM==\"?*\", ENV{MODALIAS}==\"?*\", RUN+=\"/sbin/modprobe \$" >> /etc/udev/rules.d/10-modprobe.rules
echo "env{MODALIAS}\"" >> /etc/udev/rules.d/10-modprobe.rules
echo "ACTION==\"add\", SUBSYSTEM==\"scsi_device\" RUN+=\"/sbin/modprobe sg\"" >> /etc/udev/rules.d/10-modprobe.rules
echo "ACTION==\"add\", SUBSYSTEM==\"scsi_device\", SYSFS{type}==\"0|7|14\", RUN+=\"/sbin/modprobe sd_mod\"" >> /etc/udev/rules.d/10-modprobe.rules
echo "ACTION==\"add\", SUBSYSTEM==\"scsi_device\", SYSFS{type}==\"[45]\", RUN+=\"/sbin/modprobe sr_mod\"" >> /etc/udev/rules.d/10-modprobe.rules

# OLPC specific: olpc_nand_enable, hardcodes this device file.. sigh..
#
echo "KERNEL==\"msr[0-9]*\", NAME=\"cpu/%n/msr\"" > /etc/udev/rules.d/20-cpu.rules

# FIXME: hack since sr_mod seems to fail to get loaded sometimes (#239657)
/sbin/modprobe sr_mod

/sbin/modprobe loop max_loop=16

if [ "\$quiet" != "1" ] ; then
    echo "starting udevd"
fi
/sbin/udevd --daemon

if [ "\$quiet" != "1" ] ; then
    echo "creating devices"
fi
/sbin/udevtrigger

if [ "\$quiet" != "1" ] ; then
    echo "waiting for system to settle"
fi
/sbin/udevsettle --timeout=30 || :


if [ "\$shell" == "1" ] ; then
    echo "Shell requested on kernel commandline. Exit to continue booting."
    echo
    bash
fi

# don't wait for "mtd0" as no device file will appear
if [ "\$root" != "mtd0" ] ; then

    # If we don't have the /dev/root link.. ask the user to create..
    if [ "\$waitforsymlink" != "1" ] ; then
        if [ ! -L /dev/root ] ; then
            echo
            echo "--------------------------------------"
            echo "WARNING: Cannot find root file system!"
            echo "--------------------------------------"
            echo
            echo "Create symlink /dev/root and then exit this shell to continue"
            echo "the boot sequence."
            echo
            bash
        fi
    fi

    # udevsettle might return before slow devices such as USB are in shape
    # Wait up to 60 seconds for them to appear...
    #
    if [ ! -b /dev/root ] ; then
        if [ "\$quiet" != "1" ] ; then
            echo "no root yet, udev rule will write symlink..."
            echo
            echo "waiting up to 60 seconds before dropping to emergency shell."
        fi
        COUNTDOWN=60
        while [ "x\$COUNTDOWN" != "x0" ] ; do
            if [ "\$quiet" != "1" ] ; then
                echo -n "."
            fi
            COUNTDOWN=\$((\$COUNTDOWN - 1))
            /bin/sleep 1
            if [ -e /dev/root ] ; then
	        COUNTDOWN=0
            fi
        done
    fi

    if [ ! -b /dev/root ] ; then
        echo
        echo "--------------------------------------"
        echo "WARNING: Cannot find root file system!"
        echo "--------------------------------------"
        echo
        echo "Create symlink /dev/root and then exit this shell to continue"
        echo "the boot sequence."
        echo
        bash
    fi

    if [ "\$quiet" != "1" ] ; then
        echo "mounting /dev/root"
        ls -l /dev/root
    fi

    if [ -z \$rootfstype ] ; then
        rootfstype=auto
    fi

fi

if [ "x\$check_iso" == "x1" -a -x /bin/checkisomd5 -a "x\$rootfstype" == "xiso9660" ]; then
   echo "Verifying ISO image..."
   /bin/checkisomd5 --verbose /dev/root
   if [ \$? -ne 0 ]; then
       echo "Are you SURE you want to continue?"
       echo "Press Enter to continue or ctrl-alt-del to reboot."
       read
   fi
fi 

if [ "x\$root_ro" == "x1" ] ; then
   if [ -z \$rootflags ] ; then
       rootflags="ro"
   else
       rootflags="\$rootflags,ro"
   fi
fi

if [ "x\$root_rw" == "x1" ] ; then
   if [ -z \$rootflags ] ; then
       rootflags="rw"
   else
       rootflags="\$rootflags,rw"
   fi
fi

if [ -z \$rootflags ] ; then
    mountoptions=""
else
    mountoptions=" -o\$rootflags"
fi

mount -n -t \$rootfstype \$mountoptions \$thingtomount /sysroot
RES=\$?

if [ "\$RES" != "0" ] ; then
    echo "---------------------------------"
    echo "WARNING: Cannot mount rootfs!"
    echo "---------------------------------"
    echo
    echo "Dropping to a shell. "
    echo "Mount rootfs at /sysroot and exit shell to continue. Good luck!"
    echo
    bash
fi

# Now get ready to leave the initramfs
#

# only pass kernel command line if we're launching /sbin/init
if [ "\$init" == "/sbin/init" ] ; then
    initargs=\$(cat /proc/cmdline)
else
    initargs=""
fi

# live cd helper function
do_live_from_base_loop() {
    # create a sparse file for the overlay
    dd if=/dev/null of=/overlay bs=1024 count=1 seek=$((512*1024)) 2> /dev/null
    OVERLAY_LOOPDEV=\$( losetup -f )
    losetup \$OVERLAY_LOOPDEV /overlay

    # set up the snapshot
    echo 0 \`blockdev --getsize \$BASE_LOOPDEV\` snapshot \$BASE_LOOPDEV \$OVERLAY_LOOPDEV p 8 | dmsetup create live-rw

    # set up new /dev/root symlink
    rm -f /dev/root
    ln -s /dev/mapper/live-rw /dev/root

    mount -n -t ext3 /dev/mapper/live-rw /sysroot
    # here you can modify the rw ext3 fs for testing if you don't want to
    # respin the entire rootfs (which takes ages). Example
    #
    #  echo foo > /sysroot/etc/bar.conf
    #
    # We also use it to dynamically set the system locale from the boot
    # menu on live cd's.
    #
    if [ "\$live_locale" != "" ] ; then
        echo "LANG=\$live_locale" > /sysroot/etc/sysconfig/i18n
    fi

    # copy over module options
    [ -f /etc/modprobe.conf ] && cat /etc/modprobe.conf >> /sysroot/etc/modprobe.conf

    # create rule so udev creates /dev/live symlink on real rootfs
    if [ -n "\$CDLABEL" ]; then
       echo "KERNEL==\"hd[a-z]\", BUS==\"ide\", SYSFS{removable}==\"1\", ATTRS{media}==\"cdrom\", PROGRAM=\"/lib/udev/vol_id -l %N\", RESULT==\"\$CDLABEL\", SYMLINK+=\"live\"" >> /sysroot/etc/udev/rules.d/50-udev*
       echo "KERNEL==\"sr[0-9]\", PROGRAM=\"/lib/udev/vol_id -l %N\", RESULT==\"\$CDLABEL\", SYMLINK+=\"live\"" >> /sysroot/etc/udev/rules.d/50-udev*
       echo "KERNEL==\"scd[0-9]\", PROGRAM=\"/lib/udev/vol_id -l %N\", RESULT==\"\$CDLABEL\", SYMLINK+=\"live\"" >> /sysroot/etc/udev/rules.d/50-udev*
       echo "KERNEL==\"pcd[0-9]\", PROGRAM=\"/lib/udev/vol_id -l %N\", RESULT==\"\$CDLABEL\", SYMLINK+=\"live\"" >> /sysroot/etc/udev/rules.d/50-udev*
    elif [ -n "\$LABEL" ]; then
       echo "KERNEL==\"hd[a-z]\", PROGRAM=\"/lib/udev/vol_id -l %N\", RESULT==\"\$LABEL\", SYMLINK+=\"live\"" >> /sysroot/etc/udev/rules.d/50-udev*        
       echo "KERNEL==\"hd[a-z][0-9]*\", PROGRAM=\"/lib/udev/vol_id -l %N\", RESULT==\"\$LABEL\", SYMLINK+=\"live\"" >> /sysroot/etc/udev/rules.d/50-udev*        
       echo "KERNEL==\"sd[a-z]\", PROGRAM=\"/lib/udev/vol_id -l %N\", RESULT==\"\$LABEL\", SYMLINK+=\"live\"" >> /sysroot/etc/udev/rules.d/50-udev*        
       echo "KERNEL==\"sd[a-z][0-9]*\", PROGRAM=\"/lib/udev/vol_id -l %N\", RESULT==\"\$LABEL\", SYMLINK+=\"live\"" >> /sysroot/etc/udev/rules.d/50-udev*        
    elif [ -n "\$UUID" ]; then
       echo "KERNEL==\"hd[a-z]\", PROGRAM=\"/lib/udev/vol_id -u %N\", RESULT==\"\$UUID\", SYMLINK+=\"live\"" >> /sysroot/etc/udev/rules.d/50-udev*        
       echo "KERNEL==\"hd[a-z][0-9]*\", PROGRAM=\"/lib/udev/vol_id -u %N\", RESULT==\"\$UUID\", SYMLINK+=\"live\"" >> /sysroot/etc/udev/rules.d/50-udev*        
       echo "KERNEL==\"sd[a-z]\", PROGRAM=\"/lib/udev/vol_id -u %N\", RESULT==\"\$UUID\", SYMLINK+=\"live\"" >> /sysroot/etc/udev/rules.d/50-udev*        
       echo "KERNEL==\"sd[a-z][0-9]*\", PROGRAM=\"/lib/udev/vol_id -u %N\", RESULT==\"\$UUID\", SYMLINK+=\"live\"" >> /sysroot/etc/udev/rules.d/50-udev*        
    fi

    # add rules for loop devices created by this mayflower generated init
    # i.e. /dev/live-osimg, /dev/live-osmin, /dev/live-overlay,
    #      and /dev/live-squashed
    if [ -b "\$SQUASHED_LOOPDEV" ]; then
        echo "KERNEL==\"\${SQUASHED_LOOPDEV#/dev/}\" SYMLINK+=\"live-squashed\"" >> /sysroot/etc/udev/rules.d/50-udev*
    fi
    if [ -b "\$OSMIN_SQUASHED_LOOPDEV" ]; then
        echo "KERNEL==\"\${OSMIN_SQUASHED_LOOPDEV#/dev/}\" SYMLINK+=\"live-squashed-osmin\"" >> /sysroot/etc/udev/rules.d/50-udev*
    fi
    if [ -b "\$OSMIN_LOOPDEV" ]; then
        echo "KERNEL==\"\${OSMIN_LOOPDEV#/dev/}\" SYMLINK+=\"live-osmin\"" >> /sysroot/etc/udev/rules.d/50-udev*
    fi
    echo "KERNEL==\"\${BASE_LOOPDEV#/dev/}\" SYMLINK+=\"live-osimg\"" >> /sysroot/etc/udev/rules.d/50-udev*
    echo "KERNEL==\"\${OVERLAY_LOOPDEV#/dev/}\" SYMLINK+=\"live-overlay\"" >> /sysroot/etc/udev/rules.d/50-udev*

    mount -n -o ro,remount /sysroot
}

# we might have a genMinInstDelta delta file for anaconda to take advantage of
if [ -e /sysroot/LiveOS/osmin.img ]; then
    OSMINSQFS=/sysroot/LiveOS/osmin.img
fi

if [ -n "\$OSMINSQFS" ]; then
    # decompress the delta data
    dd if=\$OSMINSQFS of=/osmin.img 2> /dev/null
    OSMIN_SQUASHED_LOOPDEV=\$( losetup -f )
    losetup \$OSMIN_SQUASHED_LOOPDEV /osmin.img
    mkdir -p /squashfs.osmin
    mount -n -t squashfs -o ro \$OSMIN_SQUASHED_LOOPDEV /squashfs.osmin
    OSMIN_LOOPDEV=\$( losetup -f )
    losetup \$OSMIN_LOOPDEV /squashfs.osmin/osmin
    umount -l /squashfs.osmin
fi

# we might have an uncompressed embedded ext3  to use as rootfs (uncompressed live)
#
if [ -e /sysroot/LiveOS/ext3fs.img ]; then
  EXT3FS="/sysroot/LiveOS/ext3fs.img"
fi

if [ -n "\$EXT3FS" ] ; then
    if [ "\$quiet" != "1" ] ; then
        echo "setting up embedded ext3 fs "
    fi

    mkdir -p /dev/mapper
    mknod /dev/mapper/control c 10 63
    modprobe dm_snapshot

    BASE_LOOPDEV=\$( losetup -f )
    losetup \$BASE_LOOPDEV \$EXT3FS
    umount -l /sysroot

    do_live_from_base_loop
fi

# we might have an embedded ext3 on squashfs to use as rootfs (compressed live)
#
if [ -e /sysroot/LiveOS/squashfs.img ]; then
  SQUASHED="/sysroot/LiveOS/squashfs.img"
fi

if [ -e "\$SQUASHED" ] ; then

    if [ "\$quiet" != "1" ] ; then
        echo "setting up embedded squash -> ext3 fs "
    fi

    mkdir -p /dev/mapper
    mknod /dev/mapper/control c 10 63
    modprobe dm_snapshot

    if [ "\$live_ram" == "1" ] ; then
        echo "Copying live image to RAM..."
        echo "(this may take a few minutes)"
        dd if=\$SQUASHED of=/squashed.img bs=512 2> /dev/null
        umount -n /sysroot
        echo "Done copying live image to RAM."
        eject -p /dev/root
        SQUASHED="/squashed.img"
    fi

    SQUASHED_LOOPDEV=\$( losetup -f )
    losetup \$SQUASHED_LOOPDEV \$SQUASHED
    mkdir -p /squashfs
    mount -n -t squashfs -o ro \$SQUASHED_LOOPDEV /squashfs

    BASE_LOOPDEV=\$( losetup -f )
    losetup \$BASE_LOOPDEV /squashfs/LiveOS/ext3fs.img
    
    umount -l /squashfs
    if [ "\$live_ram" == "0" ] ; then
        umount -l /sysroot
    fi

    do_live_from_base_loop
fi

if [ -b "\$OSMIN_LOOPDEV" ]; then
    # set up the devicemapper snapshot device, which will merge
    # the normal live fs image, and the delta, into a minimzied fs image
    echo "0 \$( blockdev --getsize \$BASE_LOOPDEV ) snapshot \$BASE_LOOPDEV \$OSMIN_LOOPDEV p 8" | dmsetup create --readonly live-osimg-min
fi

if [ "\$eshell" == "1" ] ; then
    echo "Shell requested on kernel commandline."
    echo "Rootfs is mounted ro on /sysroot. Exit to continue booting."
    echo
    bash
fi

if [ -x /sysroot\$init ] ; then

    # Leave initramfs and transition to rootfs
    kill \`pidof udevd\`
    if [ "\$quiet" != "1" ] ; then
        echo "transfering control to \$init"
    fi

    exec /sbin/run-init
    echo "---------------------------------"
    echo "WARNING: Error switching to real rootfs!"
    echo "---------------------------------"
    echo
    echo "Dropping to a shell. Good luck!"
    echo
    bash
else
    echo "---------------------------------------------------------"
    echo "WARNING: Requested \$init binary does not exist on rootfs."
    echo "---------------------------------------------------------"
    echo
    echo "Dropping to a shell. Good luck!"
    echo
    bash
fi

EOF

chmod a+x init

if [ "$opt_verbose" == "1" ] ; then
    tree -s .
    echo
    cat -n init
    echo
fi


find . | cpio --quiet -o -H newc | gzip -9 > ../initramfs
popd > /dev/null
rm -f $INITRAMFS_TARGET
cp $TEMPDIR/initramfs $INITRAMFS_TARGET
rm -rf $TEMPDIR

echo "Done; initramfs is $(du -h $INITRAMFS_TARGET | awk '{print $1}')."
echo
exit 0
