# vim: filetype=sh

# grub configuration
# ------------------

# let grub find our virtual device
update_grup_device_map()
{
    cd /
    mkdir -p boot/grub
    cat > boot/grub/device.map << END_MAP
(hd0) $loop_device
END_MAP
    cd - >/dev/null
}

# * customize boot parameters
# * fix obsolete options in /etc/default/grub
#   (https://bugs.launchpad.net/ubuntu/+source/grub2/+bug/1258597)
update_grub_conf()
{
    . /etc/default/grub
    existing_bootargs="$GRUB_CMDLINE_LINUX"
    recommended_bootargs="rootdelay=3"
    user_bootargs="$@"

    # order of precedence is:
    # user_bootargs > recommended_bootargs > existing_bootargs

    # In the case of grub, we add bootargs to grub's GRUB_CMDLINE_LINUX variable.
    # However, when deleting a bootarg, it may actually be in GRUB_CMDLINE_LINUX_DEFAULT too.

    GRUB_CMDLINE_LINUX="$(aggregate_kernel_cmdline $existing_bootargs $recommended_bootargs $user_bootargs)"

    only_minus_modifiers="$(echo "$user_bootargs" | tr ' ' '\n' | happy_grep '^-')"
    GRUB_CMDLINE_LINUX_DEFAULT="$(aggregate_kernel_cmdline $GRUB_CMDLINE_LINUX_DEFAULT $only_minus_modifiers)"

    sed -i -e "s/GRUB_CMDLINE_LINUX=.*/GRUB_CMDLINE_LINUX=\"$GRUB_CMDLINE_LINUX\"/" \
           -e "s/GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT=\"$GRUB_CMDLINE_LINUX_DEFAULT\"/" \
           -e "s/^GRUB_HIDDEN/#GRUB_HIDDEN/g" \
            /etc/default/grub

    # unless already specified, set GRUB_DISABLE_OS_PROBER to true
    # otherwise update-grub may detect and install boot entries of the host machine
    # while debootstick is building the draft image.
    if [ "$GRUB_DISABLE_OS_PROBER" = "" ]
    then
        echo >> /etc/default/grub
        echo "GRUB_DISABLE_OS_PROBER=true" >> /etc/default/grub
    fi

    # let the user know which bootargs where finally selected
    applied_kernel_cmdline=$(aggregate_kernel_cmdline $GRUB_CMDLINE_LINUX $GRUB_CMDLINE_LINUX_DEFAULT)
}

# display the grub interface on serial line
update_grub_conf_serial_line()
{
    cat >> ./etc/default/grub << EOF
GRUB_TERMINAL=serial
GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1"
EOF
}

get_grub_arch() {
    case "$(get_target_cpu "/")" in
        "amd64")
            echo "x86_64"
            ;;
        "i386")
            echo "i386"
            ;;
    esac
}

grub_install_uefi()
{
    arch=$(get_grub_arch)
    options="--target=${arch}-efi --uefi-secure-boot --no-nvram"
    if grub-install --help | grep -q force-extra-removable
    then
        options="$options --force-extra-removable"
    fi
    grub-install $options
}

grub_install_bios()
{
    grub-install "$1"
}

smart_update_initramfs()
{
    # initramfs files may be big, so when regenerating a new version
    # of the file with "update-initramfs -u", there may be an error
    # because of missing space.
    # here we remove the previous version of the file before generating
    # the new version.

    initramfs_file=$(ls /boot | grep 'initrd.img-')
    kernel_version=$(echo "$initramfs_file" | sed -e 's/initrd.img-//')
    rm -f "/boot/$initramfs_file"
    update-initramfs -c -k "$kernel_version"
}

quiet_grub_install()
{
    device=$1

    update_grup_device_map $device

    # grub-install & update-grub print messages to standard
    # error stream although most of these are just
    # informational (or minor bugs). Let's discard them.
    output="$(
        grub_install_uefi           2>&1 && \
        grub_install_bios $device   2>&1 && \
        smart_update_initramfs      2>&1 && \
        update-grub                 2>&1
    )" || return_code=$?

    echo "$output" |    happy_grep -v "No error"            | \
                        happy_grep -v "Installing"          | \
                        happy_grep -v "Generating"          | \
                        happy_grep -v "Found .* image:"     | \
                        happy_grep -v "lvmetad"             | \
                        happy_grep -v "etc.modprobe.d"      | \
                        happy_grep -v "leaked on"           | \
                        happy_grep -v "^Sourcing file"      | \
                        happy_grep -v "^Warning: os-prober" | \
                        happy_grep -v "^Systems on them"    | \
                        happy_grep -v "^Check GRUB_DISABLE" | \
                        happy_grep -v "using gzip"          | \
                        happy_grep -v "^done$" 1>&2


    # the return value we want is the one we caught
    # earlier (or none if all went well):
    return $return_code
}

configure_bootloader()
{
    # tune grub conf
    update_grub_conf $kernel_bootargs
    if [ "$config_grub_on_serial_line" -gt 0 ]
    then
        update_grub_conf_serial_line
    fi

    # disable quickboot:
    # work around grub displaying error message with our LVM setup
    # disable vt_handoff:
    # the linux console should be visible during startup (especially
    # if we must enter the root password, or in installer-mode), do
    # not switch to vt7.
    # note: even if the file etc/grub.d/10_linux is re-created
    # after an upgrade of the package grub-common, our script
    # 09_linux_custom will be executed first and take precedence.
    sed -i -e 's/quick_boot=.*/quick_boot=0/' \
           -e 's/vt_handoff=.*/vt_handoff=0/' etc/grub.d/10_linux
    mv etc/grub.d/10_linux etc/grub.d/09_linux_custom
}

install_bootloader()
{
    quiet_grub_install $loop_device
}

