Unable to boot post-update (librem13v4 + librem key)

I just sent this to support, but I thought I’d post this here as well for a wider net. Any help would be greatly appreciated!

====================
Hello! I applied the latest set of updates to my PureOS install (on my librem13v4). I am now unable to boot into the filesystem, even under Recovery Mode. I get a series of errors saying “cryptsetup failed, bad password or options?” At some point, I get dropped to an initramfs prompt, preceded by this message:

“ALERT! UUID=fb10601d-50ba-460d-9e8f-cd571d78d69a does not exist. Dropping to a shell!”

My librem key has no issue with the TOTP/HOTP check. I can get to the PureBoot Main Menu just fine. If I go to Boot Options/Show OS boot menu and select a recovery model option, I see an issue saying device not responding to setup address. It then tries to find my secret key.

Any chance for a recovery or at least getting into my filesystem to do a backup?

Does the “cryptsetup failed” message appear after you type in a password or PIN?
Did you set up decrypting your hard drive with your Librem Key and a PIN and is that how you usually decrypt your drive?
You should be able to boot into the recovery shell using your passphrase that is set up for LUKS.
Here’s some more detailed information on LUKS and setups with Librem Keys / Passphrase and what to do in such situations. Some more info would be necessary though to debug this issue from afar.

This means that your GPG key is still properly on the key. It could be that your password has too many wrong attempts? I had that on my librem key recently and had to reset it. If so you should get an according error message.

Unless your LUKS header is screwed up or you forgot your passphrase and locked your Librem Key completely, you should be able to recover a backup using a life boot. See the “Emergencies” section in the article above.

Whatever you do, this is your encrypted data. Be very careful before resetting something, etc.!

Thanks for that! I was able to mount the luks partition and start copying my files off.

Great, glad to hear that you can grab a backup of everything. You should be able to fix your system though without re-installing it. Are you on PureOS amber? I just noted that I have some pending updates for grub that I have not applied yet. This could in fact have something to do with what happened to you. Since you have your drive mounted, could you post the content of

/etc/default/grub

here? Note: If you are on a live PureOS, this would be wherever your disk is mounted, e.g., if it is mounted in /mnt/luks-drive then post the content of the file /mnt/luks-drive/etc/default/grub. Should be fixable if it’s that… If that file got screwed up that could explain why you can’t boot into the system or a recovery console.

I had the same opinion, thinking there was an issue with the grub update. Since I can’t get to a point though where I can decrypt luks on bootup, would it make any difference if I were to alter this file, assuming it got overwritten? Here’s what my /etc/default/grub file looks like now:

If you change this file, run ‘update-grub’ afterwards to update

/boot/grub/grub.cfg.

For full documentation of the options in this file, see:

info -f grub -n ‘Simple configuration’

GRUB_DEFAULT=0
GRUB_HIDDEN_TIMEOUT=0
GRUB_HIDDEN_TIMEOUT_QUIET=true
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR=lsb_release -i -s 2> /dev/null || echo Debian
GRUB_CMDLINE_LINUX_DEFAULT=“quiet nosplash noresume loglevel=3”
GRUB_CMDLINE_LINUX=""

Uncomment to enable BadRAM filtering, modify to suit your needs

This works with Linux (no patch required) and with any kernel that obtains

the memory map information from GRUB (GNU Mach, kernel of FreeBSD …)

#GRUB_BADRAM=“0x01234567,0xfefefefe,0x89abcdef,0xefefefef”

Uncomment to disable graphical terminal (grub-pc only)

#GRUB_TERMINAL=console

The resolution used on graphical terminal

note that you can use only modes which your graphic card supports via VBE

you can see them in real GRUB with the command `vbeinfo’

#GRUB_GFXMODE=640x480

Uncomment if you don’t want GRUB to pass “root=UUID=xxx” parameter to Linux

#GRUB_DISABLE_LINUX_UUID=true

Uncomment to disable generation of recovery mode menu entries

#GRUB_DISABLE_RECOVERY=“true”

Uncomment to get a beep at grub start

#GRUB_INIT_TUNE=“480 440 1”

Thanks again!

Just to make sure, this is the grub file from main hard drive, which is in this case mounted as an external drive? If this is the /etc/default/grub file from the life CD than it’s not saying much. The reason I’m suspicious is that you say you run PureOS and this one claims to be Debian… So something is of there already.

If this is the grub file from your actual hard drive, the recovery shell is missing from this file. At the end, there should be a line stating something like:

 GRUB_CMDLINE_LINUX_RECOVERY="cryptopts=target=luks-b6285bda-fe1f-4670-936e-e579eeae3752,source=UUID=b6285bda-fe1f-4670-936e-e579eeae3752,luks"

The exact specification will of course be dependent on your hard drive and setup. Assuming the grub update indeed overwrote your grub, assuming that you setup decryption with the LibremKey on PureOS using the Purism script (you still didn’t confirm any of these assumptions), you would have to manually go through patching the grub files, see the Purism script here, lines 124 - 133. Of course, you would have to replace / with wherever your external hard drive is mounted. This would be much easier from a recovery shell (you said you can’t make it into a recovery shell either)?

The final step sudo update-grub will most likely not work on a live OS since it would assume you want to update grub on the live OS itself and not on the external hard drive. update-grub is however only a shortcut to generate the grub config files and I think you can do this manually as well… Some more searching would be necessary here.

For now: Can you confirm that

  1. Above file is in fact from your mounted, main hard drive and not from the live OS.
  2. You indeed used to decrypt your LUKS drive with the LibremKey and a PIN, e.g., you saw something like this screen.

Furthermore, can you also post the content of the following files (again, not from the live OS but from your main drive:

  • etc/grub.d/10_linux
  • usr/sbin/grub-mkconfig
  • Depending on answer to question one, again the content of the etc/default/grub file

When pasting the content of these files in this editor here, please mark the file’s content after pasting and press the button in the toolbar that looks like this </> This will turn it into preformatted text, i.e., it will leave out all the formatting instructions that are in the files (since commented lines start with #, which has special meaning in markdown).

  1. I can confirm it’s from my mounted luks drive. I’m doing all of this from within initram, not a live OS.

  2. No, I don’t see that dialog. I use CoreBoot to show that the HOTP/TOTP check with the librem key is successful. From there, a menu allows me to do the default OS boot or go into the boot menu, where I can access recovery mode or other boot options. I had been using the librem key to decrypt luks automatically, but something got messed up with my keys some time back, so I had been going into recovery mode, where i can enter the luks passphrase. Not optimal, but I’ve been lazy in trying to rectify that.

  3. Requested files:
    10_linux:
    #! /bin/sh
    set -e

    #grub-mkconfig helper script.
    #Copyright © 2006,2007,2008,2009,2010 Free Software Foundation, Inc.

    #GRUB is free software: you can redistribute it and/or modify
    #it under the terms of the GNU General Public License as published by
    #the Free Software Foundation, either version 3 of the License, or
    #(at your option) any later version.

    #GRUB is distributed in the hope that it will be useful,
    #but WITHOUT ANY WARRANTY; without even the implied warranty of
    #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    #GNU General Public License for more details.

    #You should have received a copy of the GNU General Public License
    #along with GRUB. If not, see http://www.gnu.org/licenses/.

    prefix="/usr"
    exec_prefix="/usr"
    datarootdir="/usr/share"
    ubuntu_recovery=“0”
    quiet_boot=“1”
    quick_boot=“1”
    gfxpayload_dynamic=“1”
    vt_handoff=“1”

    . “$pkgdatadir/grub-mkconfig_lib”

    export TEXTDOMAIN=grub
    export TEXTDOMAINDIR="${datarootdir}/locale"

    CLASS="–class gnu-linux --class gnu --class os"
    SUPPORTED_INITS=“sysvinit:/lib/sysvinit/init systemd:/lib/systemd/systemd upstart:/sbin/upstart”

    if [ “x${GRUB_DISTRIBUTOR}” = “x” ] ; then
    OS=GNU/Linux
    else
    case ${GRUB_DISTRIBUTOR} in
    Ubuntu|Kubuntu)
    OS="${GRUB_DISTRIBUTOR}"
    ;;
    *)
    OS="${GRUB_DISTRIBUTOR} GNU/Linux"
    ;;
    esac
    CLASS="–class $(echo ${GRUB_DISTRIBUTOR} | tr ‘A-Z’ ‘a-z’ | cut -d’ ’ -f1|LC_ALL=C sed ‘s,[^[:alnum:]],,g’) ${CLASS}"
    fi

    #loop-AES arranges things so that /dev/loop/X can be our root device, but
    #the initrds that Linux uses don’t like that.
    case ${GRUB_DEVICE} in
    /dev/loop/|/dev/loop[0-9])
    GRUB_DEVICE=losetup ${GRUB_DEVICE} | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/"
    #We can’t cope with devices loop-mounted from files here.
    case ${GRUB_DEVICE} in
    /dev/
    ) ;;
    *) exit 0 ;;
    esac
    ;;
    esac

    #btrfs may reside on multiple devices. We cannot pass them as value of root= parameter
    #and mounting btrfs requires user space scanning, so force UUID in this case.
    if [ “x${GRUB_DEVICE_UUID}” = “x” ] || [ “x${GRUB_DISABLE_LINUX_UUID}” = “xtrue” ]
    || ! test -e “/dev/disk/by-uuid/${GRUB_DEVICE_UUID}”
    || ( test -e “${GRUB_DEVICE}” && uses_abstraction “${GRUB_DEVICE}” lvm ); then
    LINUX_ROOT_DEVICE=${GRUB_DEVICE}
    else
    LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}
    fi

    case x"$GRUB_FS" in
    xbtrfs)
    rootsubvol="make_system_path_relative_to_its_root /"
    rootsubvol="${rootsubvol#/}"
    if [ “x${rootsubvol}” != x ]; then
    GRUB_CMDLINE_LINUX=“rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}”
    fi;;
    xzfs)
    rpool=${grub_probe} --device ${GRUB_DEVICE} --target=fs_label 2>/dev/null || true
    bootfs="make_system_path_relative_to_its_root / | sed -e "s,@$,,""
    LINUX_ROOT_DEVICE=“ZFS=${rpool}${bootfs%/}”
    ;;
    esac

    title_correction_code=

    if [ -x /lib/recovery-mode/recovery-menu ]; then
    GRUB_CMDLINE_LINUX_RECOVERY=recovery
    else
    GRUB_CMDLINE_LINUX_RECOVERY=single
    fi
    if [ “$ubuntu_recovery” = 1 ]; then
    GRUB_CMDLINE_LINUX_RECOVERY="$GRUB_CMDLINE_LINUX_RECOVERY nomodeset"
    fi

    if [ “$vt_handoff” = 1 ]; then
    for word in $GRUB_CMDLINE_LINUX_DEFAULT; do
    if [ “$word” = splash ]; then
    GRUB_CMDLINE_LINUX_DEFAULT="$GRUB_CMDLINE_LINUX_DEFAULT $vt_handoff"
    fi
    done
    fi

    linux_entry ()
    {
    os="$1"
    version="$2"
    type="$3"
    args="$4"

    if [ -z “$boot_device_id” ]; then
    boot_device_id="$(grub_get_device_id “${GRUB_DEVICE}”)"
    fi
    if [ x$type != xsimple ] ; then
    case $type in
    recovery)
    title="$(gettext_printf “%s, with Linux %s (%s)” “${os}” “${version}” “$(gettext “${GRUB_RECOVERY_TITLE}”)”)" ;;
    init-*)
    title="$(gettext_printf “%s, with Linux %s (%s)” “${os}” “${version}” “${type#init-}”)" ;;
    *)
    title="$(gettext_printf “%s, with Linux %s” “${os}” “${version}”)" ;;
    esac
    if [ x"$title" = x"$GRUB_ACTUAL_DEFAULT" ] || [ x"Previous Linux versions>$title" = x"$GRUB_ACTUAL_DEFAULT" ]; then
    replacement_title="$(echo “Advanced options for ${OS}” | sed ‘s,>,>>,g’)>$(echo “$title” | sed ‘s,>,>>,g’)"
    quoted="$(echo “$GRUB_ACTUAL_DEFAULT” | grub_quote)"
    title_correction_code="${title_correction_code}if [ “x$default” = ‘$quoted’ ]; then default=’$(echo “$replacement_title” | grub_quote)’; fi;"
    grub_warn “$(gettext_printf “Please don’t use old title `%s’ for GRUB_DEFAULT, use `%s’ (for versions before 2.00) or `%s’ (for 2.00 or later)” “$GRUB_ACTUAL_DEFAULT” “$replacement_title” “gnulinux-advanced-$boot_device_id>gnulinux-$version-$type-$boot_device_id”)”
    fi
    echo “menuentry ‘$(echo “$title” | grub_quote)’ ${CLASS} $menuentry_id_option ‘gnulinux-$version-$type-$boot_device_id’ {” | sed “s/^/$submenu_indentation/”
    else
    echo “menuentry ‘$(echo “$os” | grub_quote)’ ${CLASS} $menuentry_id_option ‘gnulinux-simple-$boot_device_id’ {” | sed “s/^/$submenu_indentation/”
    fi
    if [ “$quick_boot” = 1 ]; then
    echo " recordfail" | sed “s/^/$submenu_indentation/”
    fi
    if [ x$type != xrecovery ] ; then
    save_default_entry | grub_add_tab
    fi

    #Use ELILO’s generic “efifb” when it’s known to be available.
    #FIXME: We need an interface to select vesafb in case efifb can’t be used.
    if [ “x$GRUB_GFXPAYLOAD_LINUX” = x ]; then
    echo " load_video" | sed “s/^/$submenu_indentation/”
    else
    if [ “x$GRUB_GFXPAYLOAD_LINUX” != xtext ]; then
    echo " load_video" | sed “s/^/$submenu_indentation/”
    fi
    fi
    if ([ “$ubuntu_recovery” = 0 ] || [ x$type != xrecovery ]) &&
    ([ “x$GRUB_GFXPAYLOAD_LINUX” != x ] || [ “$gfxpayload_dynamic” = 1 ]); then
    echo " gfxmode $linux_gfx_mode" | sed “s/^/$submenu_indentation/”
    fi

    echo " insmod gzio" | sed “s/^/$submenu_indentation/”
    echo " if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi" | sed “s/^/$submenu_indentation/”

    if [ x$dirname = x/ ]; then
    if [ -z “${prepare_root_cache}” ]; then
    prepare_root_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE} | grub_add_tab)"
    fi
    printf ‘%s\n’ “${prepare_root_cache}” | sed “s/^/$submenu_indentation/”
    else
    if [ -z “${prepare_boot_cache}” ]; then
    prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | grub_add_tab)"
    fi
    printf ‘%s\n’ “${prepare_boot_cache}” | sed “s/^/$submenu_indentation/”
    fi
    if [ x"$quiet_boot" = x0 ] || [ x"$type" != xsimple ]; then
    message="$(gettext_printf “Loading Linux %s …” ${version})"
    sed “s/^/$submenu_indentation/” << EOF
    echo ‘$(echo “$message” | grub_quote)’
    EOF
    fi
    if test -d /sys/firmware/efi && test -e “${linux}.efi.signed”; then
    sed “s/^/$submenu_indentation/” << EOF
    linux ${rel_dirname}/${basename}.efi.signed root=${linux_root_device_thisversion} ro ${args}
    EOF
    else
    sed “s/^/$submenu_indentation/” << EOF
    linux ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
    EOF
    fi
    if test -n “${initrd}” ; then
    # TRANSLATORS: ramdisk isn’t identifier. Should be translated.
    if [ x"$quiet_boot" = x0 ] || [ x"$type" != xsimple ]; then
    message="$(gettext_printf “Loading initial ramdisk …”)"
    sed “s/^/$submenu_indentation/” << EOF
    echo ‘$(echo “$message” | grub_quote)’
    EOF
    fi
    sed “s/^/$submenu_indentation/” << EOF
    initrd ${rel_dirname}/${initrd}
    EOF
    fi
    sed “s/^/$submenu_indentation/” << EOF
    }
    EOF
    }

    machine=uname -m
    case “x$machine” in
    xi?86 | xx86_64)
    list=
    for i in /boot/vmlinuz-* /vmlinuz-* /boot/kernel-* ; do
    if grub_file_is_not_garbage “$i” ; then list="$list $i" ; fi
    done ;;
    )
    list=
    for i in /boot/vmlinuz-
    /boot/vmlinux-* /vmlinuz-* /vmlinux-* /boot/kernel-* ; do
    if grub_file_is_not_garbage “$i” ; then list="$list $i" ; fi
    done ;;
    esac

    case “$machine” in
    i?86) GENKERNEL_ARCH=“x86” ;;
    mips|mips64) GENKERNEL_ARCH=“mips” ;;
    mipsel|mips64el) GENKERNEL_ARCH=“mipsel” ;;
    arm*) GENKERNEL_ARCH=“arm” ;;
    *) GENKERNEL_ARCH="$machine" ;;
    esac

    prepare_boot_cache=
    prepare_root_cache=
    boot_device_id=
    title_correction_code=

    cat << ‘EOF’
    function gfxmode {
    set gfxpayload="${1}"
    EOF
    if [ “$vt_handoff” = 1 ]; then
    cat << ‘EOF’
    if [ “${1}” = “keep” ]; then
    set vt_handoff=vt.handoff=7
    else
    set vt_handoff=
    fi
    EOF
    fi
    cat << EOF
    }
    EOF

    #Use ELILO’s generic “efifb” when it’s known to be available.
    #FIXME: We need an interface to select vesafb in case efifb can’t be used.
    if [ “x$GRUB_GFXPAYLOAD_LINUX” != x ] || [ “$gfxpayload_dynamic” = 0 ]; then
    echo “set linux_gfx_mode=$GRUB_GFXPAYLOAD_LINUX”
    else
    cat << EOF
    if [ “${recordfail}” != 1 ]; then
    if [ -e ${prefix}/gfxblacklist.txt ]; then
    if hwmatch ${prefix}/gfxblacklist.txt 3; then
    if [ ${match} = 0 ]; then
    set linux_gfx_mode=keep
    else
    set linux_gfx_mode=text
    fi
    else
    set linux_gfx_mode=text
    fi
    else
    set linux_gfx_mode=keep
    fi
    else
    set linux_gfx_mode=text
    fi
    EOF
    fi
    cat << EOF
    export linux_gfx_mode
    EOF

    #Extra indentation to add to menu entries in a submenu. We’re not in a submenu
    #yet, so it’s empty. In a submenu it will be equal to ‘\t’ (one tab).
    submenu_indentation=""

    is_top_level=true
    while [ “x$list” != “x” ] ; do
    linux=version_find_latest $list
    case $linux in
    *.efi.signed)
    # We handle these in linux_entry.
    list=echo $list | tr ' ' '\n' | grep -vx $linux | tr '\n' ' '
    continue
    ;;
    esac
    gettext_printf “Found linux image: %s\n” “$linux” >&2
    basename=basename $linux
    dirname=dirname $linux
    rel_dirname=make_system_path_relative_to_its_root $dirname
    version=echo $basename | sed -e "s,^[^0-9]*-,,g"
    alt_version=echo $version | sed -e "s,\.old$,,g"
    linux_root_device_thisversion="${LINUX_ROOT_DEVICE}"

    initrd=
    for i in “initrd.img-${version}” “initrd-${version}.img” “initrd-${version}.gz”
    “initrd-${version}” “initramfs-${version}.img”
    “initrd.img-${alt_version}” “initrd-${alt_version}.img”
    “initrd-${alt_version}” “initramfs-${alt_version}.img”
    “initramfs-genkernel-${version}”
    “initramfs-genkernel-${alt_version}”
    “initramfs-genkernel-${GENKERNEL_ARCH}-${version}”
    “initramfs-genkernel-${GENKERNEL_ARCH}-${alt_version}”; do
    if test -e “${dirname}/${i}” ; then
    initrd="$i"
    break
    fi
    done

    config=
    for i in “${dirname}/config-${version}” “${dirname}/config-${alt_version}” “/etc/kernels/kernel-config-${version}” ; do
    if test -e “${i}” ; then
    config="${i}"
    break
    fi
    done

    initramfs=
    if test -n “${config}” ; then
    initramfs=grep CONFIG_INITRAMFS_SOURCE= "${config}" | cut -f2 -d= | tr -d \"
    fi

    if test -n “${initrd}” ; then
    gettext_printf “Found initrd image: %s\n” “${dirname}/${initrd}” >&2
    elif test -z “${initramfs}” ; then
    # “UUID=” and “ZFS=” magic is parsed by initrd or initramfs. Since there’s
    # no initrd or builtin initramfs, it can’t work here.
    linux_root_device_thisversion=${GRUB_DEVICE}
    fi

    if [ “x$is_top_level” = xtrue ] && [ “x${GRUB_DISABLE_SUBMENU}” != xy ]; then
    linux_entry “${OS}” “${version}” simple
    “${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}”

     submenu_indentation="$grub_tab"
     
     if [ -z "$boot_device_id" ]; then
     boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
     fi
     # TRANSLATORS: %s is replaced with an OS name
     echo "submenu '$(gettext_printf "Advanced options for %s" "${OS}" | grub_quote)' \$menuentry_id_option 'gnulinux-advanced-$boot_device_id' {"
     is_top_level=false
    

    fi

    linux_entry “${OS}” “${version}” advanced
    “${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}”
    for supported_init in ${SUPPORTED_INITS}; do
    init_path="${supported_init#:}"
    if [ -x “${init_path}” ] && [ “$(readlink -f /sbin/init)” != “$(readlink -f “${init_path}”)” ]; then
    linux_entry “${OS}” “${version}” "init-${supported_init%%:
    }"
    “${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} init=${init_path}”
    fi
    done
    if [ “x${GRUB_DISABLE_RECOVERY}” != “xtrue” ]; then
    linux_entry “${OS}” “${version}” recovery
    “${GRUB_CMDLINE_LINUX_RECOVERY} ${GRUB_CMDLINE_LINUX}”
    fi

    list=echo $list | tr ' ' '\n' | fgrep -vx "$linux" | tr '\n' ' '
    done

    #If at least one kernel was found, then we need to
    #add a closing ‘}’ for the submenu command.
    if [ x"$is_top_level" != xtrue ]; then
    echo ‘}’
    fi

    echo “$title_correction_code”

grub-mkconfig:
#! /bin/sh
set -e

# Generate grub.cfg by inspecting /boot contents.
# Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc.
#
# GRUB is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# GRUB is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GRUB.  If not, see <http://www.gnu.org/licenses/>.

prefix="/usr"
exec_prefix="/usr"
datarootdir="/usr/share"

prefix="/usr"
exec_prefix="/usr"
sbindir="${exec_prefix}/sbin"
bindir="${exec_prefix}/bin"
sysconfdir="/etc"
PACKAGE_NAME=GRUB
PACKAGE_VERSION=2.02+dfsg1-20+deb10u2pureos1
host_os=linux-gnu
datadir="${datarootdir}"
if [ "x$pkgdatadir" = x ]; then
    pkgdatadir="${datadir}/grub"
fi
# export it for scripts
export pkgdatadir

grub_cfg=""
grub_mkconfig_dir="${sysconfdir}"/grub.d

self=`basename $0`

grub_probe="${sbindir}/grub-probe"
grub_file="${bindir}/grub-file"
grub_editenv="${bindir}/grub-editenv"
grub_script_check="${bindir}/grub-script-check"

export TEXTDOMAIN=grub
export TEXTDOMAINDIR="${datarootdir}/locale"

. "${pkgdatadir}/grub-mkconfig_lib"

# Usage: usage
# Print the usage.
usage () {
    gettext_printf "Usage: %s [OPTION]\n" "$self"
    gettext "Generate a grub config file"; echo
    echo
    print_option_help "-o, --output=$(gettext FILE)" "$(gettext "output generated config to FILE [default=stdout]")"
    print_option_help "-h, --help" "$(gettext "print this message and exit")"
    print_option_help "-v, --version" "$(gettext "print the version information and exit")"
    echo
    gettext "Report bugs to <bug-grub@gnu.org>."; echo
}

argument () {
  opt=$1
  shift

  if test $# -eq 0; then
      gettext_printf "%s: option requires an argument -- \`%s'\n" "$self" "$opt" 1>&2
      exit 1
  fi
  echo $1
}

# Check the arguments.
while test $# -gt 0
do
    option=$1
    shift

    case "$option" in
    -h | --help)
	usage
	exit 0 ;;
    -V | --version)
	echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}"
	exit 0 ;;
    -o | --output)
	grub_cfg=`argument $option "$@"`; shift;;
    --output=*)
	grub_cfg=`echo "$option" | sed 's/--output=//'`
	;;
    -*)
	gettext_printf "Unrecognized option \`%s'\n" "$option" 1>&2
	usage
	exit 1
	;;
    # Explicitly ignore non-option arguments, for compatibility.
    esac
done

if fgrep -qs '${GRUB_PREFIX}/video.lst' "${grub_mkconfig_dir}/00_header"; then
  echo "GRUB >= 2.00 has been unpacked but not yet configured." >&2
  echo "grub-mkconfig will not work until the upgrade is complete." >&2
  echo "It should run later as part of configuring the new GRUB packages." >&2
  exit 0
fi

if [ "x$EUID" = "x" ] ; then
  EUID=`id -u`
fi

if [ "$EUID" != 0 ] ; then
  root=f
  case "`uname 2>/dev/null`" in
    CYGWIN*)
      # Cygwin: Assume root if member of admin group
      for g in `id -G 2>/dev/null` ; do
	case $g in
	  0|544) root=t ;;
	esac
      done ;;
  esac
  if [ $root != t ] ; then
    gettext_printf "%s: You must run this as root\n" "$self" >&2
    exit 1
  fi
fi

set $grub_probe dummy
if test -f "$1"; then
    :
else
    gettext_printf "%s: Not found.\n" "$1" 1>&2
    exit 1
fi

# Device containing our userland.  Typically used for root= parameter.
GRUB_DEVICE="`${grub_probe} --target=device /`"
GRUB_DEVICE_UUID="`${grub_probe} --device ${GRUB_DEVICE} --target=fs_uuid 2> /dev/null`" || true

# Device containing our /boot partition.  Usually the same as GRUB_DEVICE.
GRUB_DEVICE_BOOT="`${grub_probe} --target=device /boot`"
GRUB_DEVICE_BOOT_UUID="`${grub_probe} --device ${GRUB_DEVICE_BOOT} --target=fs_uuid 2> /dev/null`" || true

# Filesystem for the device containing our userland.  Used for stuff like
# choosing Hurd filesystem module.
GRUB_FS="`${grub_probe} --device ${GRUB_DEVICE} --target=fs 2> /dev/null || echo unknown`"

if [ x"$GRUB_FS" = xunknown ]; then
    GRUB_FS="$(stat -f --printf=%T / || echo unknown)"
fi

if test -f ${sysconfdir}/default/grub ; then
  . ${sysconfdir}/default/grub
fi
for x in ${sysconfdir}/default/grub.d/*.cfg ; do
  if [ -e "${x}" ]; then
    . "${x}"
  fi
done

# XXX: should this be deprecated at some point?
if [ "x${GRUB_TERMINAL}" != "x" ] ; then
  GRUB_TERMINAL_INPUT="${GRUB_TERMINAL}"
  GRUB_TERMINAL_OUTPUT="${GRUB_TERMINAL}"
fi

termoutdefault=0
if [ "x${GRUB_TERMINAL_OUTPUT}" = "x" ]; then
    GRUB_TERMINAL_OUTPUT=gfxterm;
    termoutdefault=1;
fi

for x in ${GRUB_TERMINAL_OUTPUT}; do
    case "x${x}" in
	xgfxterm) ;;
	xconsole | xserial | xofconsole | xvga_text)
            # make sure all our children behave in conformance with ascii..
	    export LANG=C;;
	*) echo "Invalid output terminal \"${GRUB_TERMINAL_OUTPUT}\"" >&2 ; exit 1 ;;
    esac
done

GRUB_ACTUAL_DEFAULT="$GRUB_DEFAULT"

if [ "x${GRUB_ACTUAL_DEFAULT}" = "xsaved" ] ; then GRUB_ACTUAL_DEFAULT="`"${grub_editenv}" - list | sed -n '/^saved_entry=/ s,^saved_entry=,,p'`" ; fi

if [ "x${GRUB_RECOVERY_TITLE}" = "x" ]; then
  GRUB_RECOVERY_TITLE="recovery mode"
fi


# These are defined in this script, export them here so that user can
# override them.
export GRUB_DEVICE \
  GRUB_DEVICE_UUID \
  GRUB_DEVICE_BOOT \
  GRUB_DEVICE_BOOT_UUID \
  GRUB_FS \
  GRUB_FONT \
  GRUB_PRELOAD_MODULES \
  GRUB_ACTUAL_DEFAULT

# These are optional, user-defined variables.
export GRUB_DEFAULT \
  GRUB_HIDDEN_TIMEOUT \
  GRUB_HIDDEN_TIMEOUT_QUIET \
  GRUB_TIMEOUT \
  GRUB_TIMEOUT_STYLE \
  GRUB_DEFAULT_BUTTON \
  GRUB_HIDDEN_TIMEOUT_BUTTON \
  GRUB_TIMEOUT_BUTTON \
  GRUB_TIMEOUT_STYLE_BUTTON \
  GRUB_BUTTON_CMOS_ADDRESS \
  GRUB_BUTTON_CMOS_CLEAN \
  GRUB_DISTRIBUTOR \
  GRUB_CMDLINE_LINUX \
  GRUB_CMDLINE_LINUX_DEFAULT \
  GRUB_CMDLINE_XEN \
  GRUB_CMDLINE_XEN_DEFAULT \
  GRUB_CMDLINE_LINUX_XEN_REPLACE \
  GRUB_CMDLINE_LINUX_XEN_REPLACE_DEFAULT \
  GRUB_CMDLINE_NETBSD \
  GRUB_CMDLINE_NETBSD_DEFAULT \
  GRUB_CMDLINE_GNUMACH \
  GRUB_TERMINAL_INPUT \
  GRUB_TERMINAL_OUTPUT \
  GRUB_SERIAL_COMMAND \
  GRUB_DISABLE_LINUX_UUID \
  GRUB_DISABLE_RECOVERY \
  GRUB_VIDEO_BACKEND \
  GRUB_GFXMODE \
  GRUB_BACKGROUND \
  GRUB_THEME \
  GRUB_GFXPAYLOAD_LINUX \
  GRUB_DISABLE_OS_PROBER \
  GRUB_INIT_TUNE \
  GRUB_SAVEDEFAULT \
  GRUB_ENABLE_CRYPTODISK \
  GRUB_BADRAM \
  GRUB_OS_PROBER_SKIP_LIST \
  GRUB_DISABLE_SUBMENU \
  GRUB_RECORDFAIL_TIMEOUT \
  GRUB_RECOVERY_TITLE

if test "x${grub_cfg}" != "x"; then
  rm -f "${grub_cfg}.new"
  oldumask=$(umask); umask 077
  exec > "${grub_cfg}.new"
  umask $oldumask
fi
gettext "Generating grub configuration file ..." >&2
echo >&2

cat << EOF
#
# DO NOT EDIT THIS FILE
#
# It is automatically generated by $self using templates
# from ${grub_mkconfig_dir} and settings from ${sysconfdir}/default/grub
#
EOF


for i in "${grub_mkconfig_dir}"/* ; do
  case "$i" in
    # emacsen backup files. FIXME: support other editors
    *~) ;;
    # emacsen autosave files. FIXME: support other editors
    */\#*\#) ;;
    *)
      if grub_file_is_not_garbage "$i" && test -x "$i" ; then
        echo
        echo "### BEGIN $i ###"
        "$i"
        echo "### END $i ###"
      fi
    ;;
  esac
done

if [ "x${grub_cfg}" != "x" ] && ! grep "^password" ${grub_cfg}.new >/dev/null; then
  chmod 444 ${grub_cfg}.new || true
fi

if test "x${grub_cfg}" != "x" ; then
  if ! ${grub_script_check} ${grub_cfg}.new; then
    # TRANSLATORS: %s is replaced by filename
    gettext_printf "Syntax errors are detected in generated GRUB config file.
Ensure that there are no errors in /etc/default/grub
and /etc/grub.d/* files or please file a bug report with
%s file attached." "${grub_cfg}.new" >&2
    echo >&2
    exit 1
  else
    # none of the children aborted with error, install the new grub.cfg
    mv -f ${grub_cfg}.new ${grub_cfg}
  fi
fi

gettext "done" >&2
echo >&2

Thanks again!

Apologies for the late reply and thanks for confirming that these are indeed the files that go with your boot drive. All of them look like the LUKS decryption with a smartcard has been undone. How or why this would be the case is pretty weird / unclear to me.

Do you know which keys got screwed up? The keys on your librem key or the decryption file that lies on your drive? Since you can access your hard drive, your passphrase is surely still working. Remotely finding the issue here is really difficult. My feeling - based on very limited information and to be taken with a grain of salt - is that only your boot menu is screwed up. You could go through the Purism provided script to set up LUKS decryption with a LibremKey. Of course, make sure that your librem key actually has functioning keys on there. Without running the script, I’d go through it line by line and see if everything except for grub is indeed in place and if those tests work. I’m not sure how comfortable you are with this.

If your keys are all screwed up and lost on the librem key, you could also go through removing smart-card decryption and through setting it up again with a fresh pair of keys. This article, mentioned above as well, goes through that in detail.

Either way, this is strange, I don’t have any good advice on how to easily fix it - sorry. Make sure you have backup of all your data before you start messing with LUKS more :slight_smile:

No worries, and I appreciate your time in helping me out! I think the librem key got messed up at some point. Around the start of the year, I was trying to set up my librem key to autodecrypt my drive, and something then got messed up. Since I could get in through Recovery Mode, I just did that until I got some motivation to back out those changes or reset.

As it happens, with my data backed up, I opted to do a reinstall on the laptop and oem factory reset on the librem key. That got me back up and running cleanly now, so I don’t have access to my old etc files. Sorry about that.

Thanks again!

@mathemagician Understandable, glad you could get the full data backup and that this worked out well.