#!/bin/bash

set -e

. /usr/share/debconf/confmodule

clean_up ()
{
    cd /
    if [ "$CLEANUP" -gt 2 ]; then
        rm -fr "$TMPDIR"/upper "$TMPDIR"/initrd "$TMPDIR"/initrd.lz "$TMPDIR"/microcode.cpio
    fi
    if [ "$CLEANUP" -gt 1 ]; then
        umount "$TMPDIR"/chroot/dev "$TMPDIR"/chroot/sys "$TMPDIR"/chroot/proc "$TMPDIR"/chroot "$TMPDIR"/lower
        rm -fr "$TMPDIR"
    fi
    if [ "$CLEANUP" -gt 0 ] && [ -n "$DISK" ] && [ -d "$DISK" ]; then
        umount "$DISK"
        rmdir "$DISK"
    fi
}

generate_kernel_initrd()
{
    TMPDIR=$(mktemp -d)
    cd "$TMPDIR"
    mkdir lower upper workdir chroot initrd chroot/dev chroot/proc chroot/sys

    mount "$DISK"/casper/filesystem.squashfs lower
    mount -t overlay -o lowerdir="$TMPDIR"/lower,upperdir="$TMPDIR"/upper,workdir="$TMPDIR"/workdir none chroot
    mount -o bind /dev chroot/dev
    mount -o bind /proc chroot/proc
    mount -o bind /sys chroot/sys
    CLEANUP=2

    cd chroot
    apt-get download "$@"
    mkdir -p "$DISK"/debs/main
    cp -v linux*.deb "$DISK"/debs
    cd ..

    cat > chroot/generate_initrd.sh <<ENDLINE
#!/bin/bash

dpkg -i /*.deb
ENDLINE
    chmod +x chroot/generate_initrd.sh
    chroot chroot /generate_initrd.sh

    if [ -d upper/boot ]; then
        chmod 644 upper/boot/*
    fi
}

update_kernel_initrd ()
{
    release="$1"
    echo "INFO: using kernel release $release"
    ls -l upper/boot/
    if [ "$(lsb_release -cs)" = 'focal' ]; then
        cp -v "upper/boot/vmlinuz-$release" "$DISK"/casper/vmlinuz
    elif [ -f "upper/boot/vmlinuz-$release.efi.signed" ]; then
        cp -v "upper/boot/vmlinuz-$release.efi.signed" "$DISK"/casper/vmlinuz.efi
        cp -v "upper/boot/vmlinuz-$release" "$DISK"/casper/vmlinuz
    else
        cp -v "upper/boot/vmlinuz-$release" "$DISK"/casper/vmlinuz.efi
    fi

    cp "upper/boot/initrd.img-$release" .

    while file "initrd.img-$release" | grep cpio >/dev/null 2>&1; do
        offset=$(cpio -t <"initrd.img-$release" 2>&1 >/dev/null | awk '{print $1}')
        dd if="initrd.img-$release" of="initrd.img-$release.microcode" bs=512 count="$offset" >/dev/null 2>&1
        dd if="initrd.img-$release" of="initrd.img-$release.tmp" bs=512 skip="$offset" >/dev/null 2>&1
        mv "initrd.img-$release.tmp" "initrd.img-$release"
        cat <"initrd.img-$release.microcode" >>microcode.cpio
        rm "initrd.img-$release.microcode"
    done

    cd initrd
    if file "../initrd.img-$release" | grep -i gzip >/dev/null 2>&1; then
        zcat "../initrd.img-$release" | cpio --quiet -id
    elif file "../initrd.img-$release" | grep -i lzma >/dev/null 2>&1; then
        lzcat "../initrd.img-$release" | cpio --quiet -id
    elif file "../initrd.img-$release" | grep -i lz4 >/dev/null 2>&1; then
        lz4cat "../initrd.img-$release" | cpio --quiet -id
    else
        file "../initrd.img-$release"
        echo "WARNING: It doesn't deal with this format yet."
    fi
    rm "../initrd.img-$release"
    UUID="$(uuidgen -r)"
    echo "$UUID" > conf/uuid.conf
    # The xz will use 90 seconds to compress, while lz4 just use 6 seconds.
    #find . 2>/dev/null | cpio --quiet -o -H newc | xz --verbose -9 --format=lzma >"../initrd.lz"
    find . 2>/dev/null | cpio --quiet -o -H newc | lz4 --verbose -9 -l >"../initrd.lz"
    cd ..

    if [ -f "microcode.cpio" ]; then
        CONCAT=("microcode.cpio" "initrd.lz")
    else
        CONCAT=("initrd.lz")
    fi

    cat "${CONCAT[@]}" > "$DISK"/casper/initrd
    echo "$UUID" > "$DISK"/.disk/casper-uuid
    CLEANUP=3
}

update_recovery_partition()
{
    [ -z "$1" ] && exit
    trap clean_up EXIT
    DISK=$(mktemp -d)
    mount "$1" "$DISK"
    CLEANUP=1
    cd "$DISK" || exit
    VERSION=$(file "$DISK/casper/vmlinuz" | grep -oP "version [^ ]*" | awk '{print $2}')
    CHROOT_SCRIPT="$DISK"/scripts/chroot-scripts/os-post/00-kernel-update.sh
    EMERGENCY_SCRIPT="$DISK"/scripts/emergency-scripts/00-installer-update.sh
    case "$VERSION" in
        (5.4.0-*-generic)
            if dpkg --compare-versions "$VERSION" lt '5.4.0-42-generic'; then
                generate_kernel_initrd linux-headers-5.4.0-42-generic linux-image-5.4.0-42-generic linux-modules-5.4.0-42-generic linux-modules-extra-5.4.0-42-generic linux-headers-5.4.0-42
                update_kernel_initrd 5.4.0-42-generic
                mkdir -p "$(dirname "$CHROOT_SCRIPT")"
                if ! grep 5.4.0-42-generic "$CHROOT_SCRIPT" >/dev/null 2>&1; then
                    [ ! -e "$CHROOT_SCRIPT" ] && echo '#!/bin/sh' > "$CHROOT_SCRIPT"
                    cat >> "$CHROOT_SCRIPT" <<ENDLINE
set -x
if [ -x /usr/share/ubuntu/scripts/pool.sh ]; then
    /usr/share/ubuntu/scripts/pool.sh
    apt-get install --yes --allow-unauthenticated linux-headers-5.4.0-42-generic linux-image-5.4.0-42-generic linux-modules-5.4.0-42-generic linux-modules-extra-5.4.0-42-generic linux-headers-5.4.0-42
fi
ENDLINE
                   mkdir -p "$(dirname "$EMERGENCY_SCRIPT")"
                   [ ! -e "$EMERGENCY_SCRIPT" ] && cat > "$EMERGENCY_SCRIPT" << ENDLINE
#!/bin/sh
set -x
chroot /root /bin/sh /cdrom/scripts/chroot-scripts/os-post/00-kernel-update.sh
ENDLINE
                fi
            else
                echo "Linux kernel in recovery partition is new enough. No need to update it."
            fi
            ;;
        (5.6.0-*-oem)
            if dpkg --compare-versions "$VERSION" lt '5.6.0-1020-oem'; then
                generate_kernel_initrd linux-headers-5.6.0-1020-oem linux-image-5.6.0-1020-oem linux-modules-5.6.0-1020-oem linux-oem-5.6-headers-5.6.0-1020
                update_kernel_initrd 5.6.0-1020-oem
                mkdir -p "$(dirname "$CHROOT_SCRIPT")"
                if ! grep 5.6.0-1020-oem "$CHROOT_SCRIPT" >/dev/null 2>&1; then
                    [ ! -e "$CHROOT_SCRIPT" ] && echo '#!/bin/sh' > "$CHROOT_SCRIPT"
                    cat >> "$CHROOT_SCRIPT" <<ENDLINE
set -x
if [ -x /usr/share/ubuntu/scripts/pool.sh ]; then
    /usr/share/ubuntu/scripts/pool.sh
    apt-get install --yes --allow-unauthenticated linux-headers-5.6.0-1020-oem linux-image-5.6.0-1020-oem linux-modules-5.6.0-1020-oem linux-oem-5.6-headers-5.6.0-1020
fi
ENDLINE
                   mkdir -p "$(dirname "$EMERGENCY_SCRIPT")"
                   [ ! -e "$EMERGENCY_SCRIPT" ] && cat > "$EMERGENCY_SCRIPT" << ENDLINE
#!/bin/sh
set -x
chroot /root /bin/sh /cdrom/scripts/chroot-scripts/os-post/00-kernel-update.sh
ENDLINE
                fi
            else
                echo "Linux kernel in recovery partition is new enough. No need to update it."
            fi
            ;;
    esac
}

case "$1" in
    (configure)
        if dpkg-query -W -f='${Status}\n' dell-recovery 2>&1 | grep "install ok installed" >/dev/null 2>&1; then
            TARGET=$(python3 -c "import Dell.recovery_common as magic; target=magic.find_partition(); print(target.decode('utf8')) if type(target) is bytes else print(target)")
        elif dpkg-query -W -f='${Status}\n' ubuntu-recovery 2>&1 | grep "install ok installed" >/dev/null 2>&1; then
            TARGET=$(python3 -c "import ubunturecovery.recovery_common as magic; target=magic.find_partition('PQSERVICE'); print(target.decode('utf8')) if type(target) is bytes else print(target)")
        else
            TARGET=""
        fi
        update_recovery_partition "$TARGET"
    ;;
esac

#DEBHELPER#
