#!/bin/sh

## Copyright 2022 Arnaud Ferraris <aferraris@debian.org>
##
## SPDX-License-Identifier: GPL-3.0-or-later

set -e

VERSION="$1"
if [ -z "${VERSION}" ]; then
    echo "Usage: $0 VERSION"
    exit 1
fi

BOOTPART="boot"
LATESTKERNEL="$(linux-version list | tail -1)"

# Only update the bootimg for the most recent kernel
if linux-version compare "${VERSION}" lt "${LATESTKERNEL}"; then
    echo "I: Not updating bootimg for ${VERSION} < ${LATESTKERNEL}, quitting..."
    exit 0
fi

# Fetch the device parameters
for x in $(cat /proc/cmdline); do
    case $x in
        mobile.qcomsoc=*) QCOMSOC=${x#mobile.qcomsoc=} ;;
        mobile.vendor=*) VENDOR=${x#mobile.vendor=} ;;
        mobile.model=*) MODEL=${x#mobile.model=} ;;
        mobile.variant=*) VARIANT=${x#mobile.variant=} ;;
    esac
done

if [ -z "${MODEL}" ]; then
    echo "Probably running in a VM, not updating bootimg..."
    exit 0
fi

if [ "${VARIANT}" ]; then
    DTBNAME="${QCOMSOC}-${VENDOR}-${MODEL}-${VARIANT}"
else
    DTBNAME="${QCOMSOC}-${VENDOR}-${MODEL}"
fi

ROOTDEVID="$(findmnt -n -o UUID /)"

if [ "$(findmnt -n -o SOURCE /)" = "/dev/mapper/root" ]; then
    ROOTDEVID="/dev/mapper/root"
fi

if [ -z "${ROOTDEVID}" ]; then
    echo "W: Unable to determine root filesystem UUID, quitting..."
    exit 1
fi

TMPDIR=$(mktemp -d /tmp/bootimg.XXXXXX)

if [ -e /dev/disk/by-partlabel/boot_b ]; then
    # Check slot currently in use: `unpack_bootimg` prints information about
    # the boot image, including the kernel cmdline it contains; if we can find
    # the UUID of the current root partition, then we can assume that's the
    # one.
    BOOTPART="boot_a"
    BOOTIMG_PARAMS="$(unpack_bootimg --format mkbootimg --out ${TMPDIR} --boot_img /dev/disk/by-partlabel/boot_a 2>/dev/null || true)"
    if ! echo "${BOOTIMG_PARAMS}" | grep -q "${ROOTDEVID}"; then
        BOOTPART="boot_b"
        BOOTIMG_PARAMS="$(unpack_bootimg --format mkbootimg --out ${TMPDIR} --boot_img /dev/disk/by-partlabel/boot_b || true)"
        if ! echo "${BOOTIMG_PARAMS}" | grep -q "${ROOTDEVID}"; then
            echo "ERROR: unable to determine current boot slot, aborting..."
            exit 1
        fi
    fi
else
    # Extract the boot image, saving the information in a format that can be used
    # directly by `mkbootimg`
    BOOTIMG_PARAMS="$(unpack_bootimg --format mkbootimg --out ${TMPDIR} --boot_img /dev/disk/by-partlabel/boot)"
fi

# The `cmdline` part of the arguments are quoted, but those will be discarded
# by the shell when reusing the params, so the kernel cmdline parameters will
# be interpreted as command-line arguments for `mkbootimg`, ultimately leading
# to an "unrecognized arguments" error.
# In order to avoid this, save the kernel cmdline in a separate variable and
# strip the `--cmdline` and `--board` (the latter being unused in our case)
# arguments from the params
CMDLINE="$(echo "${BOOTIMG_PARAMS}" | sed "s/.*--cmdline '\(.*\)'/\1/")"
CLEAN_PARAMS="$(echo "${BOOTIMG_PARAMS}" | sed -e "s/ --cmdline '.*'//" -e "s/ --board '.*'//")"

# Append the DTB to the kernel and copy the new initrd
cat /boot/vmlinuz-${VERSION} /usr/lib/linux-image-${VERSION}/${DTBNAME}.dtb > ${TMPDIR}/kernel
cp /boot/initrd.img-${VERSION} ${TMPDIR}/ramdisk

if echo "${CLEAN_PARAMS}" | grep -q -- "--header_version 2"; then
    # Copy the DTB if needed
    cp /usr/lib/linux-image-${VERSION}/${DTBNAME}.dtb ${TMPDIR}/dtb
fi

# Create the new boot image and write it to disk
mkbootimg -o ${TMPDIR}/boot.img ${CLEAN_PARAMS} --cmdline "${CMDLINE}"
dd if=${TMPDIR}/boot.img of=/dev/disk/by-partlabel/${BOOTPART} bs=1M

# Cleanup and exit
rm -rf ${TMPDIR}
