#!/bin/sh

rm /etc/udev/rules.d/magicmemory.rules

udev_quirks() {
    # udev kills slow scripts
    if [ "$SETSID" != "1" ]
    then
        SETSID=1 setsid "$0" "$@" &
        exit
    fi

    # udev might call twice
    mkdir /tmp/MagicMemory || exit
}

nickel_wait() {
    while sleep 1
    do
        pidof nickel && sleep 5 && break
    done
}

nickel_grab_env() {
    eval $(xargs -0 < /proc/$(pidof nickel)/environ)
    export $(xargs -0 < /proc/$(pidof nickel)/environ | sed -e 's@=[^ ]*@@g')
    cd / # PWD sanity
}

nickel_kill() {
    killall nickel
    killall sickel # 3.16.10 watchdog
    while sleep 1
    do
        pidof nickel || break
    done
}

progress_stop() {
    rm /tmp/magicmemory-progress*
}

progress() {
    local pid="$RANDOM$RANDOM"
    progress_stop
    touch /tmp/magicmemory-progress-"$pid"
    [ $PRODUCT != trilogy ] && PREFIX=$PRODUCT-
    local i=0
    while [ -e /tmp/magicmemory-progress-"$pid" ]
    do
        if [ "$1" == "black" ]
        then
            cat /dev/zero | /usr/local/Kobo/pickel showpic 1
        elif [ "$1" == "white" ]
        then
            tr '\x00' '\xff' < /dev/zero | /usr/local/Kobo/pickel showpic 1
        else
            i=$((($i+${1:-1})%11))
            zcat /etc/images/"$PREFIX"on-"$i".raw.gz | /usr/local/Kobo/pickel showpic 1
        fi

        sleep 3
     done
}

nuke() {
    progress 0 &
    sleep 999999
    exit
}

mmc_detect() {
    local error=1
    for driver in /sys/bus/platform/drivers/*/unbind
    do
        driver=$(dirname "$driver")
        for device in "$driver"/*/
        do
            if [ -e "$device"/mmc_host/mmc${1:-0} ]
            then
                MMC_DRIVER="$driver"
                MMC_DEVICE=$(basename "$device")
                error=0
            fi
        done
    done

    return $error
}

mmc_unbind() {
    sync && sync
    echo "$MMC_DEVICE" > "$MMC_DRIVER"/unbind && sleep 1
}

mmc_bind() {
    mmc_unbind
    echo "$MMC_DEVICE" > "$MMC_DRIVER"/bind && sleep 1
}

# Main:
udev_quirks
rm /magic_udev
mmc_detect 2 || exit
nickel_wait
nickel_grab_env
nickel_kill
umount /mnt/*
sync

# Mount the old stuff.
sleep 1
progress 10 &
mount -t tmpfs none /mnt # also prevents /mnt/sd mounts
mkdir -p /mnt/OLD/rootfs /mnt/OLD/recoveryfs /mnt/OLD/data
mkdir -p /mnt/NEW/rootfs /mnt/NEW/recoveryfs /mnt/NEW/data
mount -o bind / /mnt/OLD/rootfs || nuke
mount -o ro /dev/mmcblk0p2 /mnt/OLD/recoveryfs || nuke
mount -o ro /dev/mmcblk0p3 /mnt/OLD/data || nuke

# Card removal.
sleep 1
progress black &

while blockdev --getsize64 /dev/mmcblk1
do
    mmc_unbind
    sleep 5
    mmc_bind
done

# Card insertion.
sleep 1
progress white &

while ! blockdev --getsize64 /dev/mmcblk1
do
    mmc_unbind
    sleep 5
    mmc_bind
done

sleep 1
progress 1 &

# Copy bootloader and kernel.
dd if=/dev/mmcblk0 of=/dev/mmcblk1 bs=64k count=$((1+$(cat /sys/block/mmcblk0/mmcblk0p1/start)/128))
mmc_bind # force redetect partitions

# Make a new user partition.
# del 3, new 4 (1-???), new 3 (???-end), del 4, type 3 b (FAT32), write
echo $'\nd\n3\nn\np\n4\n1\n\nn\np\n\n\nd\n4\nt\n3\nb\nw\n' | fdisk /dev/mmcblk1 || nuke
mmc_bind # force redetect partitions
dd if=/dev/zero of=/dev/mmcblk1p3 bs=64k count=1
mkfs.vfat -n KOBOeReader /dev/mmcblk1p3 || nuke
mount /dev/mmcblk1p3 /mnt/NEW/data || nuke

# Create the new recoveryfs.
dd if=/dev/zero of=/dev/mmcblk1p2 bs=64k count=1
/mnt/OLD/recoveryfs/sbin/mkfs.ext4 -L recoveryfs -m 0 /dev/mmcblk1p2 || nuke
mount /dev/mmcblk1p2 /mnt/NEW/recoveryfs || nuke

# Create the new rootfs.
dd if=/dev/zero of=/dev/mmcblk1p1 bs=64k count=1
/mnt/OLD/recoveryfs/sbin/mkfs.ext4 -L rootfs -m 0 /dev/mmcblk1p1 || nuke
mount /dev/mmcblk1p1 /mnt/NEW/rootfs || nuke

# Actually copy the data.
cp -a /mnt/OLD/. /mnt/NEW/.
umount /mnt/OLD/* /mnt/NEW/*

# Done.
sync
reboot
sleep 9999
