From 5ca3069b2387d937decceb60debf410652f386ab Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Mon, 8 Jul 2019 22:19:27 -0500 Subject: [PATCH 01/11] config-gui: add optional param to set file_selector title Signed-off-by: Matt DeVillier --- initrd/bin/config-gui.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/initrd/bin/config-gui.sh b/initrd/bin/config-gui.sh index eb3b2f481..51647aee3 100755 --- a/initrd/bin/config-gui.sh +++ b/initrd/bin/config-gui.sh @@ -8,6 +8,7 @@ file_selector() { FILE="" FILE_LIST=$1 MENU_MSG=${2:-"Choose the file"} + MENU_TITLE=${3:-"Select your File"} # create file menu options if [ `cat "$FILE_LIST" | wc -l` -gt 0 ]; then option="" @@ -23,7 +24,7 @@ file_selector() { done < $FILE_LIST MENU_OPTIONS="$MENU_OPTIONS a Abort" - whiptail --clear --title "Select your File" \ + whiptail --clear --title "${MENU_TITLE}" \ --menu "${MENU_MSG} [1-$n, a to abort]:" 20 120 8 \ -- $MENU_OPTIONS \ 2>/tmp/whiptail || die "Aborting" From 34394032defb73ddd7f099ab5820364f854a29fe Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Mon, 8 Jul 2019 22:20:45 -0500 Subject: [PATCH 02/11] config-gui: add optional param to bypass menu Add optional parameter to bypass menu selection and immediately select a menu option. This allows us to call the 'Set Boot Device' option directly, saving the user an unnecessary step. Signed-off-by: Matt DeVillier --- initrd/bin/config-gui.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/initrd/bin/config-gui.sh b/initrd/bin/config-gui.sh index 51647aee3..4dbe65265 100755 --- a/initrd/bin/config-gui.sh +++ b/initrd/bin/config-gui.sh @@ -51,16 +51,24 @@ file_selector() { fi } +param=$1 + while true; do + if [ ! -z "$param" ]; then + # use first char from parameter + menu_choice=${param::1} + unset param + else unset menu_choice whiptail --clear --title "Config Management Menu" \ --menu "This menu lets you change settings for the current BIOS session.\n\nAll changes will revert after a reboot,\n\nunless you also save them to the running BIOS." 20 90 10 \ 'b' ' Change the /boot device' \ 's' ' Save the current configuration to the running BIOS' \ - 'x' ' Exit' \ + 'x' ' Return to Main Menu' \ 2>/tmp/whiptail || recovery "GUI menu failed" menu_choice=$(cat /tmp/whiptail) + fi case "$menu_choice" in "x" ) From c982be5bd48314bb3e20ca4a277995a19192a697 Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Mon, 8 Jul 2019 22:23:04 -0500 Subject: [PATCH 03/11] config-gui: filter out invalid boot device options use similar filtering logic as with USB drives to provide the user a more sane list of boot device options. Show user only valid bootable partitions, not block devices. There's no point in showing /dev/nvme0 and /dev/nvme0n1 (eg) when /dev/nvme0n1p[1..n] (eg) exist, as the former are not valid boot devices. Signed-off-by: Matt DeVillier --- initrd/bin/config-gui.sh | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/initrd/bin/config-gui.sh b/initrd/bin/config-gui.sh index 4dbe65265..e1ea3ebd1 100755 --- a/initrd/bin/config-gui.sh +++ b/initrd/bin/config-gui.sh @@ -59,15 +59,15 @@ while true; do menu_choice=${param::1} unset param else - unset menu_choice - whiptail --clear --title "Config Management Menu" \ + unset menu_choice + whiptail --clear --title "Config Management Menu" \ --menu "This menu lets you change settings for the current BIOS session.\n\nAll changes will revert after a reboot,\n\nunless you also save them to the running BIOS." 20 90 10 \ 'b' ' Change the /boot device' \ 's' ' Save the current configuration to the running BIOS' \ 'x' ' Return to Main Menu' \ 2>/tmp/whiptail || recovery "GUI menu failed" - menu_choice=$(cat /tmp/whiptail) + menu_choice=$(cat /tmp/whiptail) fi case "$menu_choice" in @@ -76,8 +76,21 @@ while true; do ;; "b" ) CURRENT_OPTION=`grep 'CONFIG_BOOT_DEV=' /tmp/config | tail -n1 | cut -f2 -d '=' | tr -d '"'` - find /dev -name 'sd*' -o -name 'nvme*' > /tmp/filelist.txt - file_selector "/tmp/filelist.txt" "Choose the default /boot device.\n\nCurrently set to $CURRENT_OPTION." + fdisk -l | grep "Disk" | cut -f2 -d " " | cut -f1 -d ":" > /tmp/disklist.txt + # filter out extraneous options + > /tmp/boot_device_list.txt + for i in `cat /tmp/disklist.txt`; do + # remove block device from list if numeric partitions exist, since not bootable + let DEV_NUM_PARTITIONS=`ls -1 $i* | wc -l`-1 + if [ ${DEV_NUM_PARTITIONS} -eq 0 ]; then + echo $i >> /tmp/boot_device_list.txt + else + ls $i* | tail -${DEV_NUM_PARTITIONS} >> /tmp/boot_device_list.txt + fi + done + file_selector "/tmp/boot_device_list.txt" \ + "Choose the default /boot device.\n\nCurrently set to $CURRENT_OPTION." \ + "Boot Device Selection" if [ "$FILE" == "" ]; then return else From 258783e98e34a038e5b4448b320910baf02e9f17 Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Mon, 8 Jul 2019 22:25:57 -0500 Subject: [PATCH 04/11] gui-init: don't reboot after updating TOTP/HOTP Updating TOTP/HOTP is mainly necessary after a user updates their firmware, and no need to force another reboot. Signed-off-by: Matt DeVillier --- initrd/bin/gui-init | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/initrd/bin/gui-init b/initrd/bin/gui-init index f9f12f680..23045137a 100755 --- a/initrd/bin/gui-init +++ b/initrd/bin/gui-init @@ -97,10 +97,9 @@ update_totp() read /bin/seal-libremkey else - echo "Once you have scanned the QR code, hit Enter to reboot" + echo "Once you have scanned the QR code, hit Enter to continue" read fi - /bin/reboot } # enable USB to load modules for external kb From 0690c8c011ea188f078564422594691804213927 Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Mon, 8 Jul 2019 22:27:40 -0500 Subject: [PATCH 05/11] gui-init: use direct boot device selection If the boot device is invalid or unabled to be mounted and the user opts to select a new boot device, jump directly to that menu option and avoid the additional step of showing the config main menu. Signed-off-by: Matt DeVillier --- initrd/bin/gui-init | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/initrd/bin/gui-init b/initrd/bin/gui-init index 23045137a..bac7a298d 100755 --- a/initrd/bin/gui-init +++ b/initrd/bin/gui-init @@ -15,7 +15,7 @@ mount_boot() if [ ! -e "$CONFIG_BOOT_DEV" ]; then if (whiptail $CONFIG_ERROR_BG_COLOR --clear --title "ERROR: $CONFIG_BOOT_DEV missing!" \ --yesno "The /boot device $CONFIG_BOOT_DEV could not be found!\n\nYou will need to configure the correct device for /boot.\n\nWould you like to configure the /boot device now?" 30 90) then - config-gui.sh + config-gui.sh boot_device_select else # exit to main menu break @@ -27,7 +27,7 @@ mount_boot() if [ $? -ne 0 ]; then if (whiptail $CONFIG_ERROR_BG_COLOR --clear --title 'ERROR: Cannot mount /boot' \ --yesno "The /boot partition at $CONFIG_BOOT_DEV could not be mounted!\n\nWould you like to configure the /boot device now?" 30 90) then - config-gui.sh + config-gui.sh boot_device_select else recovery "Unable to mount /boot" fi From 928f003550dbe48fe25205fe5e9911b6423d9191 Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Tue, 9 Jul 2019 09:02:46 -0500 Subject: [PATCH 06/11] config-gui: add 'Full Reset' option Add Full Reset option to clear all GPG keys and user settings, both from the local filesystem and running firmware, and clear/reset the TPM Signed-off-by: Matt DeVillier --- initrd/bin/config-gui.sh | 42 ++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/initrd/bin/config-gui.sh b/initrd/bin/config-gui.sh index e1ea3ebd1..ed31c478f 100755 --- a/initrd/bin/config-gui.sh +++ b/initrd/bin/config-gui.sh @@ -64,6 +64,7 @@ while true; do --menu "This menu lets you change settings for the current BIOS session.\n\nAll changes will revert after a reboot,\n\nunless you also save them to the running BIOS." 20 90 10 \ 'b' ' Change the /boot device' \ 's' ' Save the current configuration to the running BIOS' \ + 'r' ' Clear GPG key(s) and reset all user settings' \ 'x' ' Return to Main Menu' \ 2>/tmp/whiptail || recovery "GUI menu failed" @@ -115,15 +116,40 @@ while true; do cbfs -o /tmp/config-gui.rom -d "heads/initrd/etc/config.user" fi cbfs -o /tmp/config-gui.rom -a "heads/initrd/etc/config.user" -f /etc/config.user - - if (whiptail --title 'Update ROM?' \ - --yesno "This will reflash your BIOS with the updated version\n\nDo you want to proceed?" 16 90) then - /bin/flash.sh /tmp/config-gui.rom - whiptail --title 'BIOS Updated Successfully' \ - --msgbox "BIOS updated successfully.\n\nIf your keys have changed, be sure to re-sign all files in /boot\nafter you reboot.\n\nPress Enter to reboot" 16 60 + ;; + "r" ) + # prompt for confirmation + if (whiptail --title 'Reset Configuration?' \ + --yesno "This will clear all GPG keys, clear boot signatures and checksums, + \nreset the /boot device, clear/reset the TPM (if present), + \nand reflash your BIOS with the cleaned configuration. + \n\nDo you want to proceed?" 16 90) then + # read current firmware + /bin/flash.sh -r /tmp/config-gui.rom + if [ ! -s /tmp/config-gui.rom ]; then + whiptail $CONFIG_ERROR_BG_COLOR --title 'ERROR: BIOS Read Failed!' \ + --msgbox "Unable to read BIOS" 16 60 + exit 1 + fi + # clear local keyring + rm /.gnupg/* | true + # clear /boot signatures/checksums + mount -o remount,rw /boot + rm /boot/kexec* | true + mount -o remount,ro /boot + # clear GPG keys and user settings + for i in `cbfs -o /tmp/config-gui.rom -l | grep -e "heads/"`; do + cbfs -o /tmp/config-gui.rom -d $i + done + # flash cleared ROM + /bin/flash.sh -c /tmp/config-gui.rom + # reset TPM if present + if [ "$CONFIG_TPM" = "y" ]; then + /bin/tpm-reset + fi + whiptail --title 'Configuration Reset Updated Successfully' \ + --msgbox "Configuration reset and BIOS updated successfully.\n\nPress Enter to reboot" 16 60 /bin/reboot - else - exit 0 fi ;; esac From 29f89ae47b33ee827dd8a29c89a745ba500457c6 Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Tue, 9 Jul 2019 11:41:31 -0500 Subject: [PATCH 07/11] gpg_flash_rom(): ensure files exist before adding to CBFS Check that any files added to cbfs exist before attempting to add them, so flashing doesn't fail after a reset. Signed-off-by: Matt DeVillier --- initrd/bin/gpg-gui.sh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/initrd/bin/gpg-gui.sh b/initrd/bin/gpg-gui.sh index ea8efa732..6a7523745 100755 --- a/initrd/bin/gpg-gui.sh +++ b/initrd/bin/gpg-gui.sh @@ -105,7 +105,9 @@ gpg_flash_rom() { if (cbfs -o /tmp/gpg-gui.rom -l | grep -q "heads/initrd/.gnupg/trustdb.gpg") then cbfs -o /tmp/gpg-gui.rom -d "heads/initrd/.gnupg/trustdb.gpg" fi - cbfs -o /tmp/gpg-gui.rom -a "heads/initrd/.gnupg/trustdb.gpg" -f /.gnupg/trustdb.gpg + if [ -e /.gnupg/trustdb.gpg ]; then + cbfs -o /tmp/gpg-gui.rom -a "heads/initrd/.gnupg/trustdb.gpg" -f /.gnupg/trustdb.gpg + fi #Remove old method owner trust exported file if (cbfs -o /tmp/gpg-gui.rom -l | grep -q "heads/initrd/.gnupg/otrust.txt") then @@ -116,8 +118,9 @@ gpg_flash_rom() { if (cbfs -o /tmp/gpg-gui.rom -l | grep -q "heads/initrd/etc/config.user") then cbfs -o /tmp/gpg-gui.rom -d "heads/initrd/etc/config.user" fi - cbfs -o /tmp/gpg-gui.rom -a "heads/initrd/etc/config.user" -f /etc/config.user - + if [ -e /etc/config.user ]; then + cbfs -o /tmp/gpg-gui.rom -a "heads/initrd/etc/config.user" -f /etc/config.user + fi /bin/flash.sh /tmp/gpg-gui.rom if (whiptail --title 'BIOS Flashed Successfully' \ From 5ff3849c169e8afe0ea61cc995cf3c70e192b059 Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Tue, 9 Jul 2019 11:43:06 -0500 Subject: [PATCH 08/11] kecec_select_boot: default to Y when setting new boot option Next prompt will be to ensure GPG key is attached, which defaults to Y, so default here as well for consistency Signed-off-by: Matt DeVillier --- initrd/bin/kexec-select-boot | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/initrd/bin/kexec-select-boot b/initrd/bin/kexec-select-boot index 36b35a613..793d6a79b 100755 --- a/initrd/bin/kexec-select-boot +++ b/initrd/bin/kexec-select-boot @@ -186,11 +186,12 @@ scan_options() { save_default_option() { read \ -n 1 \ - -p "Saving a default will modify the disk. Proceed? (y/n): " \ + -p "Saving a default will modify the disk. Proceed? (Y/n): " \ default_confirm echo - if [ "$default_confirm" = "y" ]; then + [ "$default_confirm" = "" ] && default_confirm="y" + if [[ "$default_confirm" = "y" || "$default_confirm" = "Y" ]]; then if kexec-save-default \ -b "$bootdir" \ -d "$paramsdev" \ From c33209add18122894c10b8fef810de7eec04d559 Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Tue, 9 Jul 2019 16:46:14 -0500 Subject: [PATCH 09/11] confirm_gpg_card: prompt for retry on detection failure Initial card detection can sometimes fail, so prompt the user to remove/reinsert their GPG card before retrying. Since errexit is likely set, disable it prior to calling --card-status so we can handle the error ourself, then re-set if necessary when done. Signed-off-by: Matt DeVillier --- initrd/etc/functions | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/initrd/etc/functions b/initrd/etc/functions index 7a2cfdacb..d6cf0c14e 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -136,8 +136,28 @@ confirm_gpg_card() # setup the USB so we can reach the GPG card enable_usb - gpg --card-status \ - || die "gpg card read failed" + echo -e "\nVerifying presence of GPG card...\n" + # ensure we don't exit without retrying + errexit=$(set -o | grep errexit | awk '{print $2}') + set +e + gpg --card-status > /dev/null + if [ $? -ne 0 ]; then + # prompt for reinsertion and try a second time + read -n1 -r -p \ + "Can't access GPG key; remove and reinsert, then press Enter to retry. " \ + ignored + # restore prev errexit state + if [ "$errexit" = "on" ]; then + set -e + fi + # retry card status + gpg --card-status > /dev/null \ + || die "gpg card read failed" + fi + # restore prev errexit state + if [ "$errexit" = "on" ]; then + set -e + fi } From e8e1032027d646615a007bf48282c0f9bbf66520 Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Tue, 9 Jul 2019 16:53:40 -0500 Subject: [PATCH 10/11] gpg_add_key_reflash: handle user cancellation if user chooses abort option, exit without flashing ROM Signed-off-by: Matt DeVillier --- initrd/bin/gpg-gui.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/initrd/bin/gpg-gui.sh b/initrd/bin/gpg-gui.sh index 6a7523745..0b016b626 100755 --- a/initrd/bin/gpg-gui.sh +++ b/initrd/bin/gpg-gui.sh @@ -196,7 +196,12 @@ gpg_add_key_reflash() { find /media -name '*.key' > /tmp/filelist.txt find /media -name '*.asc' >> /tmp/filelist.txt file_selector "/tmp/filelist.txt" "Choose your GPG public key" - PUBKEY=$FILE + # bail if user didn't select a file + if [ "$FILE" = "" ]; then + return + else + PUBKEY=$FILE + fi /bin/flash.sh -r /tmp/gpg-gui.rom if [ ! -s /tmp/gpg-gui.rom ]; then From a27affcc7d751018f0e9bd5c685e4fd04a4f1908 Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Wed, 31 Jul 2019 22:53:04 -0500 Subject: [PATCH 11/11] flash.sh: persist serial in cbfs Librem devices store their serial number as a text file in cbfs; persist this across flashes. Signed-off-by: Matt DeVillier --- initrd/bin/flash.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/initrd/bin/flash.sh b/initrd/bin/flash.sh index e89c9a98c..121b42b1e 100755 --- a/initrd/bin/flash.sh +++ b/initrd/bin/flash.sh @@ -43,6 +43,12 @@ flash_rom() { preserve_rom /tmp/${CONFIG_BOARD}.rom \ || die "$ROM: Config preservation failed" fi + # persist serial number from CBFS + if cbfs -r serial_number > /tmp/serial 2>/dev/null; then + echo "Persisting system serial" + cbfs -o /tmp/${CONFIG_BOARD}.rom -d serial_number 2>/dev/null || true + cbfs -o /tmp/${CONFIG_BOARD}.rom -a serial_number -f /tmp/serial + fi flashrom $FLASHROM_OPTIONS -w /tmp/${CONFIG_BOARD}.rom \ || die "$ROM: Flash failed"