#!/bin/bash
# postinst script for oem-fix-boot-hole
#
# see: dh_installdeb(1)

set -e

# summary of how this script can be called:
#        * <postinst> `configure' <most-recently-configured-version>
#        * <old-postinst> `abort-upgrade' <new version>
#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>
#          <new-version>
#        * <postinst> `abort-remove'
#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
#          <failed-install-package> <version> `removing'
#          <conflicting-package> <version>
# for details, see https://www.debian.org/doc/debian-policy/ or
# the debian-policy package

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"/lower1 "$TMPDIR"/lower2
        rm -fr "$TMPDIR"
    fi
    if [ "$CLEANUP" -gt 0 ] && [ -n "$RECOVERYPART" ] && [ -d "$RECOVERYPART" ]; then
        umount "$RECOVERYPART"
        rmdir "$RECOVERYPART"
    fi
}

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

    mount "$RECOVERYPART"/casper/filesystem.squashfs lower1
    mount "$RECOVERYPART"/casper/installer.squashfs lower2
    mount -t overlay -o lowerdir="$TMPDIR"/lower2:"$TMPDIR"/lower1,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

    # copy recovery hook script to chroot/usr/share/initramfs-tools/scripts/casper-bottom/
    cp /usr/share/oem-fix-boot-hole/initrd-casper-hooks/scripts/casper-bottom/99ubuntu_custom-recovery \
        chroot/usr/share/initramfs-tools/scripts/casper-bottom

    cd chroot
    apt-get download "$@"
    cp -v linux*.deb "$RECOVERYPART"/recovery/factory/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/
    # copy new vmlinuz to recovery partition
    cp -v "upper/boot/vmlinuz-$release" "$RECOVERYPART"/casper/vmlinuz

    # repack initrd with recovery hook scripts
    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
    find . 2>/dev/null | cpio --quiet -o -H newc | xz --verbose -9 --format=lzma >"../initrd.lz"
    cd ..

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

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

update_recovery_partition()
{
    cd "$RECOVERYPART" || exit
    VERSION=$(file "$RECOVERYPART/casper/vmlinuz" | grep -oP "version [^ ]*" | awk '{print $2}')
    case "$VERSION" in
        (4.15.0-*-dell300x)
            # XXX: stay clam until urgent case
            ;;
        (4.15.0-*-oem)
            # Remove linux-oem from recovery due to previous update
            rm -rf "$RECOVERYPART"/recovery/factory/debs/linux-headers-4.15.0-1096-oem*
            rm -rf "$RECOVERYPART"/recovery/factory/debs/linux-image-4.15.0-1096-oem*
            rm -rf "$RECOVERYPART"/recovery/factory/debs/linux-modules-4.15.0-1096-oem*
            rm -rf "$RECOVERYPART"/recovery/factory/debs/linux-oem*
            generate_kernel_initrd linux-dell300x-headers-4.15.0-1004 linux-dell300x linux-headers-4.15.0-1004-dell300x \
                linux-headers-dell300x linux-image-4.15.0-1004-dell300x linux-image-dell300x linux-modules-4.15.0-1004-dell300x
            update_kernel_initrd 4.15.0-1004-dell300x
            ;;
    esac
}

case "$1" in
    configure)
        trap clean_up EXIT
        [ -z "$(blkid --label ESP)" ] && exit
        # mount recovery partition
        RECOVERYPART=$(mktemp -d)
        mkdir -p "$RECOVERYPART"
        mount "$(blkid --label ESP)" "$RECOVERYPART"
        CLEANUP=1
        VERSION=$(dpkg-deb -f "$RECOVERYPART"/pool/main/g/grub2/grub-efi-amd64_*_amd64.deb Version)
        if dpkg --compare-versions "$VERSION" lt '2.02-2ubuntu8.17'; then
            # install boot.tar.gz to <recovery partition>/boot/grub/
            tar xvf /usr/share/oem-fix-boot-hole/boot.tar.gz -C "$RECOVERYPART"/boot
            # copy *.deb into <recovery partition>/recovery/factory/debs/
            cp /usr/share/oem-fix-boot-hole/debs/*.deb "$RECOVERYPART"/recovery/factory/debs
            # copy grubx64.efi.signed to <recovery partition>/EFI/BOOT/
            install -m 755 /usr/share/oem-fix-boot-hole/EFI/BOOT/BOOTx64.EFI "$RECOVERYPART"/EFI/BOOT
            install -m 755 /usr/share/oem-fix-boot-hole/EFI/BOOT/grubx64.efi "$RECOVERYPART"/EFI/BOOT
            # add 20-remove-oem-kernel.sh to <recovery partition>/recovery/factory/OEM_post_install_hook
            cp /usr/share/oem-fix-boot-hole/recovery-assets/factory/OEM_post_install_hook/20-remove-oem-kernel.sh \
                "$RECOVERYPART"/recovery/factory/OEM_post_install_hook
            # update kernel & initrd to <recovery partition>/casper/
            update_recovery_partition
        else
            echo "GRUB in recovery partition is new enough. No need to update it."
        fi
    ;;

    abort-upgrade|abort-remove|abort-deconfigure)
        # umount recovery partition if it's mounted eariler
        if [ "$(mount | grep -c "$(blkid --label ESP)")" -ne 0 ]; then
            RECOVERYPART="$(mount | grep -c "$(blkid --label ESP)" | awk '{print \$3}')"
            umount "$RECOVERYPART"
            rm -rf "$RECOVERYPART"
        fi
    ;;

    *)
        echo "postinst called with unknown argument \`$1'" >&2
        exit 1
    ;;
esac

# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.

#DEBHELPER#

exit 0
