diff --git a/Makefile b/Makefile index 305347c8..e77ecc56 100644 --- a/Makefile +++ b/Makefile @@ -395,6 +395,7 @@ bin_modules-$(CONFIG_FLASHTOOLS) += flashtools bin_modules-$(CONFIG_NEWT) += newt bin_modules-$(CONFIG_CAIRO) += cairo bin_modules-$(CONFIG_FBWHIPTAIL) += fbwhiptail +bin_modules-$(CONFIG_NITROKEY) += nitrokey-hotp-verification $(foreach m, $(bin_modules-y), \ $(call map,initrd_bin_add,$(call bins,$m)) \ @@ -502,11 +503,13 @@ $(initrd_tmp_dir)/etc/config: FORCE -e 's/\\\"//g' \ > $@ \ ) - $(call do,HASH,$(GIT_HASH) $(GIT_STATUS), \ + $(call do,HASH,$(GIT_HASH) $(GIT_STATUS) $(BOARD), \ echo export GIT_HASH=\'$(GIT_HASH)\' \ >> $@ ; \ echo export GIT_STATUS=$(GIT_STATUS) \ >> $@ ; \ + echo export CONFIG_BOARD=$(BOARD) \ + >> $@ ; \ ) # Ensure that the initrd depends on all of the modules that produce diff --git a/initrd/bin/flash-gui.sh b/initrd/bin/flash-gui.sh new file mode 100755 index 00000000..191d977b --- /dev/null +++ b/initrd/bin/flash-gui.sh @@ -0,0 +1,219 @@ +#!/bin/sh +# +set -e -o pipefail +. /etc/functions +. /etc/config + +mount_usb(){ +# Mount the USB boot device + if ! grep -q /media /proc/mounts ; then + mount-usb "$CONFIG_USB_BOOT_DEV" || USB_FAILED=1 + if [ $USB_FAILED -ne 0 ]; then + if [ ! -e "$CONFIG_USB_BOOT_DEV" ]; then + whiptail --title 'USB Drive Missing' \ + --msgbox "Insert your USB drive and press Enter to continue." 16 60 USB_FAILED=0 + mount-usb "$CONFIG_USB_BOOT_DEV" || USB_FAILED=1 + fi + if [ $USB_FAILED -ne 0 ]; then + whiptail $CONFIG_ERROR_BG_COLOR --title 'ERROR: Mounting /media Failed' \ + --msgbox "Unable to mount $CONFIG_USB_BOOT_DEV" 16 60 + fi + fi + fi +} + +file_selector() { + FILE="" + FILE_LIST=$1 + MENU_MSG=${2:-"Choose the file"} +# create file menu options + if [ `cat "$FILE_LIST" | wc -l` -gt 0 ]; then + option="" + while [ -z "$option" ] + do + MENU_OPTIONS="" + n=0 + while read option + do + n=`expr $n + 1` + option=$(echo $option | tr " " "_") + MENU_OPTIONS="$MENU_OPTIONS $n ${option}" + done < $FILE_LIST + + MENU_OPTIONS="$MENU_OPTIONS a Abort" + whiptail --clear --title "Select your File" \ + --menu "${MENU_MSG} [1-$n, a to abort]:" 20 120 8 \ + -- $MENU_OPTIONS \ + 2>/tmp/whiptail || die "Aborting" + + option_index=$(cat /tmp/whiptail) + + if [ "$option_index" = "a" ]; then + option="a" + return + fi + + option=`head -n $option_index $FILE_LIST | tail -1` + if [ "$option" == "a" ]; then + return + fi + done + if [ -n "$option" ]; then + FILE=$option + fi + else + whiptail $CONFIG_ERROR_BG_COLOR --title 'ERROR: No Files Found' \ + --msgbox "No Files found matching the pattern. Aborting." 16 60 + exit 1 + fi +} + +while true; do + unset menu_choice + whiptail --clear --title "BIOS Management Menu" \ + --menu 'Select the BIOS function to perform' 20 90 10 \ + 'f' ' Flash the BIOS with a new ROM' \ + 'c' ' Flash the BIOS with a new cleaned ROM' \ + 'a' ' Add GPG key to BIOS image' \ + 'r' ' Add GPG key to running BIOS' \ + 'x' ' Exit' \ + 2>/tmp/whiptail || recovery "GUI menu failed" + + menu_choice=$(cat /tmp/whiptail) + + case "$menu_choice" in + "x" ) + exit 0 + ;; + f|c ) + if (whiptail --title 'Flash the BIOS with a new ROM' \ + --yesno "This requires you insert a USB drive containing:\n* Your BIOS image (*.rom)\n\nAfter you select this file, this program will reflash your BIOS\n\nDo you want to proceed?" 16 90) then + mount_usb + if grep -q /media /proc/mounts ; then + find /media -name '*.rom' > /tmp/filelist.txt + file_selector "/tmp/filelist.txt" "Choose the ROM to flash" + if [ "$FILE" == "" ]; then + return + else + ROM=$FILE + fi + + if (whiptail --title 'Flash ROM?' \ + --yesno "This will replace your old ROM with $ROM\n\nDo you want to proceed?" 16 90) then + if [ "$menu_choice" == "c" ]; then + /bin/flash.sh -c $ROM + else + /bin/flash.sh $ROM + fi + whiptail --title 'ROM Flashed Successfully' \ + --msgbox "$ROM flashed successfully. Press Enter to reboot" 16 60 + umount /media + /bin/reboot + else + exit + fi + fi + fi + ;; + "a" ) + if (whiptail --title 'ROM and GPG public key required' \ + --yesno "This requires you insert a USB drive containing:\n* Your GPG public key (*.key or *.asc)\n* Your BIOS image (*.rom)\n\nAfter you select these files, this program will reflash your BIOS\n\nDo you want to proceed?" 16 90) then + mount_usb + if grep -q /media /proc/mounts ; then + find /media -name '*.key' > /tmp/filelist.txt + find /media -name '*.asc' >> /tmp/filelist.txt + file_selector "/tmp/filelist.txt" "Choose your GPG public key" + if [ "$FILE" == "" ]; then + return + else + PUBKEY=$FILE + fi + + find /media -name '*.rom' > /tmp/filelist.txt + file_selector "/tmp/filelist.txt" "Choose the ROM to load your key onto" + if [ "$FILE" == "" ]; then + return + else + ROM=$FILE + fi + + cat $PUBKEY | gpg --import + cp $ROM /tmp/gpg-gui.rom + if (cbfs -o /tmp/gpg-gui.rom -l | grep -q "heads/initrd/.gnupg/pubring.gpg") then + cbfs -o /tmp/gpg-gui.rom -d "heads/initrd/.gnupg/pubring.gpg" + fi + cbfs -o /tmp/gpg-gui.rom -a "heads/initrd/.gnupg/pubring.gpg" -f /.gnupg/pubring.gpg + + 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 (whiptail --title 'Flash ROM?' \ + --yesno "This will replace your old ROM with $ROM\n\nDo you want to proceed?" 16 90) then + /bin/flash.sh /tmp/gpg-gui.rom + whiptail --title 'ROM Flashed Successfully' \ + --msgbox "$ROM flashed 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 + umount /media + /bin/reboot + else + exit 0 + fi + fi + fi + ;; + "r" ) + if (whiptail --title 'GPG public key required' \ + --yesno "Flashing the running BIOS requires you insert a USB drive containing:\n* Your GPG public key (*.key or *.asc)\n\nAfter you select this file, this program will copy and reflash your BIOS\n\nDo you want to proceed?" 16 90) then + mount_usb + if grep -q /media /proc/mounts ; then + 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 + + /bin/flash.sh -r /tmp/gpg-gui.rom + if [ ! -s /tmp/gpg-gui.rom ]; then + whiptail $CONFIG_ERROR_BG_COLOR --title 'ERROR: BIOS Read Failed!' \ + --msgbox "Unable to read BIOS" 16 60 + exit 1 + fi + + cat $PUBKEY | gpg --import + if (cbfs -o /tmp/gpg-gui.rom -l | grep -q "heads/initrd/.gnupg/pubring.gpg") then + cbfs -o /tmp/gpg-gui.rom -d "heads/initrd/.gnupg/pubring.gpg" + fi + cbfs -o /tmp/gpg-gui.rom -a "heads/initrd/.gnupg/pubring.gpg" -f /.gnupg/pubring.gpg + + 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 (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/gpg-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 + umount /media + /bin/reboot + else + exit 0 + fi + fi + fi + ;; + "g" ) + confirm_gpg_card + echo "********************************************************************************" + echo "*" + echo "* INSTRUCTIONS:" + echo "* Type 'admin' and then 'generate' and follow the prompts to generate a GPG key." + echo "*" + echo "********************************************************************************" + gpg --card-edit + ;; + esac + +done +exit 0 diff --git a/initrd/bin/flash.sh b/initrd/bin/flash.sh new file mode 100755 index 00000000..4b70ac8a --- /dev/null +++ b/initrd/bin/flash.sh @@ -0,0 +1,72 @@ +#!/bin/sh +# +# based off of flashrom-x230 +# +set -e -o pipefail +. /etc/functions +. /etc/config + +case "$CONFIG_BOARD" in + librem* ) + FLASHROM_OPTIONS='-p internal:laptop=force_I_want_a_brick,ich_spi_mode=hwseq' + ;; + x230* ) + FLASHROM_OPTIONS='--force --noverify-all --programmer internal --ifd --image bios' + ;; + "kgpe-d16" ) + FLASHROM_OPTIONS='--force --noverify --programmer internal' + ;; + * ) + die "ERROR: No board has been configured!\n\nEach board requires specific flashrom options and it's unsafe to flash without them.\n\nAborting." + ;; +esac + +flash_rom() { + ROM=$1 + if [ "$READ" -eq 1 ]; then + flashrom $FLASHROM_OPTIONS -r "${ROM}.1" \ + || die "$ROM: Read failed" + flashrom $FLASHROM_OPTIONS -r "${ROM}.2" \ + || die "$ROM: Read failed" + flashrom $FLASHROM_OPTIONS -r "${ROM}.3" \ + || die "$ROM: Read failed" + if [ `sha256sum ${ROM}.[123] | cut -f1 -d ' ' | uniq | wc -l` -eq 1 ]; then + mv ${ROM}.1 $ROM + rm ${ROM}.[23] + else + die "$ROM: Read inconsistent" + fi + else + cp "$ROM" /tmp/${CONFIG_BOARD}.rom + sha256sum /tmp/${CONFIG_BOARD}.rom + if [ "$CLEAN" -eq 0 ]; then + preserve_rom /tmp/${CONFIG_BOARD}.rom \ + || die "$ROM: Config preservation failed" + fi + + flashrom $FLASHROM_OPTIONS -w /tmp/${CONFIG_BOARD}.rom \ + || die "$ROM: Flash failed" + fi +} + +if [ "$1" == "-c" ]; then + CLEAN=1 + READ=0 + ROM="$2" +elif [ "$1" == "-r" ]; then + CLEAN=0 + READ=1 + ROM="$2" + touch $ROM +else + CLEAN=0 + READ=0 + ROM="$1" +fi + +if [ ! -e "$ROM" ]; then + die "Usage: $0 [-c|-r] " +fi + +flash_rom $ROM +exit 0 diff --git a/initrd/bin/flashrom-kgpe-d16.sh b/initrd/bin/flashrom-kgpe-d16.sh deleted file mode 100755 index 801c1b83..00000000 --- a/initrd/bin/flashrom-kgpe-d16.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh -. /etc/functions - -if [ "$1" = "-c" ]; then - CLEAN=1 - ROM="$2" -else - CLEAN=0 - ROM="$1" -fi - -if [ ! -e "$ROM" ]; then - die "Usage: $0 [-c] /media/kgpe-d16.rom" -fi - -cp "$ROM" /tmp/kgpe-d16.rom -sha256sum /tmp/kgpe-d16.rom -if [ "$CLEAN" -eq 0 ]; then - preserve_rom /tmp/kgpe-d16.rom \ - || die "$ROM: Config preservation failed" -fi - -flashrom \ - --force \ - --noverify \ - --programmer internal \ - -w /tmp/kgpe-d16.rom \ -|| die "$ROM: Flash failed" - -warn "Reboot and hopefully it works..." -exit 0 diff --git a/initrd/bin/flashrom-x230.sh b/initrd/bin/flashrom-x230.sh deleted file mode 100755 index 81150aab..00000000 --- a/initrd/bin/flashrom-x230.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh -. /etc/functions - -if [ "$1" = "-c" ]; then - CLEAN=1 - ROM="$2" -else - CLEAN=0 - ROM="$1" -fi - -if [ ! -e "$ROM" ]; then - die "Usage: $0 [-c] /media/x230.rom" -fi - -cp "$ROM" /tmp/x230.rom -sha256sum /tmp/x230.rom -if [ "$CLEAN" -eq 0 ]; then - preserve_rom /tmp/x230.rom \ - || die "$ROM: Config preservation failed" -fi - -flashrom \ - --force \ - --noverify-all \ - --programmer internal \ - --ifd \ - --image bios \ - -w /tmp/x230.rom \ -|| die "$ROM: Flash failed" - -warn "Reboot and hopefully it works..." -exit 0 diff --git a/initrd/bin/gui-init b/initrd/bin/gui-init index 12269f7c..4577dd63 100755 --- a/initrd/bin/gui-init +++ b/initrd/bin/gui-init @@ -148,6 +148,7 @@ while true; do 'g' ' Generate new TOTP secret' \ 'p' ' Reset the TPM' \ 's' ' Update checksums and sign all files in /boot' \ + 'f' ' Flash/Update the BIOS -->' \ 'r' ' <-- Return to main menu' \ 2>/tmp/whiptail || recovery "GUI menu failed" @@ -245,6 +246,11 @@ while true; do continue fi + if [ "$totp_confirm" = "f" ]; then + flash-gui.sh + continue + fi + if [ "$totp_confirm" = "y" -o -n "$totp_confirm" ]; then # Try to boot the default mount_boot