diff --git a/.circleci/config.yml b/.circleci/config.yml index b78f6960f..1e7572b9a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -194,6 +194,7 @@ jobs: - build/x86/coreboot-4.15 - build/x86/coreboot-4.17 - build/x86/coreboot-4.19 + - build/x86/coreboot-git - build/ppc64/coreboot-git - save_cache: #Generate cache for the exact same modules definitions if hash is not previously existing diff --git a/Makefile b/Makefile index 2617fcf1a..06b2913e6 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,10 @@ GIT_STATUS := $(shell \ fi) HEADS_GIT_VERSION := $(shell git describe --abbrev=7 --tags --dirty) -CB_OUTPUT_BASENAME := heads-$(BOARD)-$(HEADS_GIT_VERSION) +# Override BRAND_NAME to set the name displayed in the UI, filenames, versions, etc. +BRAND_NAME ?= Heads + +CB_OUTPUT_BASENAME := $(shell echo $(BRAND_NAME) | tr A-Z a-z)-$(BOARD)-$(HEADS_GIT_VERSION) CB_OUTPUT_FILE := $(CB_OUTPUT_BASENAME).rom CB_OUTPUT_FILE_GPG_INJ := $(CB_OUTPUT_BASENAME)-gpg-injected.rom CB_BOOTBLOCK_FILE := $(CB_OUTPUT_BASENAME).bootblock @@ -180,6 +183,7 @@ FORCE: define install_config = sed -e 's!@BOARD_BUILD_DIR@!$(board_build)!g' \ -e 's!@BLOB_DIR@!$(pwd)/blobs!g' \ + -e 's!@BRAND_NAME@!$(BRAND_NAME)!g' \ "$1" > "$2" endef @@ -513,6 +517,8 @@ bin_modules-$(CONFIG_TPM2_TOOLS) += tpm2-tools bin_modules-$(CONFIG_BASH) += bash bin_modules-$(CONFIG_POWERPC_UTILS) += powerpc-utils bin_modules-$(CONFIG_IO386) += io386 +bin_modules-$(CONFIG_IOPORT) += ioport +bin_modules-$(CONFIG_ZSTD) += zstd $(foreach m, $(bin_modules-y), \ $(call map,initrd_bin_add,$(call bins,$m)) \ @@ -568,6 +574,7 @@ $(COREBOOT_UTIL_DIR)/superiotool/superiotool: \ initrd-y += $(pwd)/blobs/dev.cpio initrd-y += $(build)/$(initrd_dir)/modules.cpio initrd-y += $(build)/$(initrd_dir)/tools.cpio +initrd-y += $(build)/$(initrd_dir)/board.cpio initrd-$(CONFIG_HEADS) += $(build)/$(initrd_dir)/heads.cpio #$(build)/$(initrd_dir)/.build: $(build)/$(initrd_dir)/initrd.cpio.xz @@ -597,6 +604,17 @@ $(build)/$(initrd_dir)/initrd.cpio.xz: $(initrd-y) bundle-$(CONFIG_LINUX_BUNDLED) += $(board_build)/$(LINUX_IMAGE_FILE).bundled all: $(bundle-y) +# The board.cpio is built from the board's initrd/ directory. It contains +# board-specific support scripts. + +ifeq ($(wildcard $(pwd)/boards/$(BOARD)/initrd),) +$(build)/$(initrd_dir)/board.cpio: + cpio -H newc -o "$@" +else +$(build)/$(initrd_dir)/board.cpio: FORCE + $(call do-cpio,$@,$(pwd)/boards/$(BOARD)/initrd) +endif + # # The heads.cpio is built from the initrd directory in the # Heads tree. @@ -633,6 +651,8 @@ $(initrd_tmp_dir)/etc/config: FORCE >> $@ ; \ echo export CONFIG_BOARD=$(BOARD) \ >> $@ ; \ + echo export CONFIG_BRAND_NAME=$(BRAND_NAME) \ + >> $@ ; \ ) # Ensure that the initrd depends on all of the modules that produce diff --git a/blobs/librem_jail/README b/blobs/librem_jail/README new file mode 100644 index 000000000..25e13c2c0 --- /dev/null +++ b/blobs/librem_jail/README @@ -0,0 +1 @@ +This directory contains firmware/microcode needed for the Intel AX200 WiFi module, its Bluetooth counterparts, and the Bluetooth component (ar3k) of Ath9k WiFi modules. It is synchronized via the main system firmware (Pureboot) at each boot, and should not be modified. diff --git a/blobs/librem_jail/ar3k/AthrBT_0x11020100.dfu b/blobs/librem_jail/ar3k/AthrBT_0x11020100.dfu new file mode 100644 index 000000000..659f999f7 Binary files /dev/null and b/blobs/librem_jail/ar3k/AthrBT_0x11020100.dfu differ diff --git a/blobs/librem_jail/ar3k/ramps_0x11020100_40.dfu b/blobs/librem_jail/ar3k/ramps_0x11020100_40.dfu new file mode 100644 index 000000000..0d4045276 Binary files /dev/null and b/blobs/librem_jail/ar3k/ramps_0x11020100_40.dfu differ diff --git a/blobs/librem_jail/intel/ibt-20-1-3.ddc b/blobs/librem_jail/intel/ibt-20-1-3.ddc new file mode 100644 index 000000000..6e067796e Binary files /dev/null and b/blobs/librem_jail/intel/ibt-20-1-3.ddc differ diff --git a/blobs/librem_jail/intel/ibt-20-1-3.sfi b/blobs/librem_jail/intel/ibt-20-1-3.sfi new file mode 100644 index 000000000..e73e3ab30 Binary files /dev/null and b/blobs/librem_jail/intel/ibt-20-1-3.sfi differ diff --git a/blobs/librem_jail/iwlwifi-cc-a0-59.ucode b/blobs/librem_jail/iwlwifi-cc-a0-59.ucode new file mode 100644 index 000000000..ddf1e6bda Binary files /dev/null and b/blobs/librem_jail/iwlwifi-cc-a0-59.ucode differ diff --git a/boards/librem_13v2/librem_13v2.config b/boards/librem_13v2/librem_13v2.config index 066516903..bd0d18b86 100644 --- a/boards/librem_13v2/librem_13v2.config +++ b/boards/librem_13v2/librem_13v2.config @@ -3,7 +3,7 @@ CONFIG_LINUX_CONFIG=config/linux-librem_common.config CONFIG_COREBOOT_CONFIG=config/coreboot-librem_13v2.config export CONFIG_COREBOOT=y -export CONFIG_COREBOOT_VERSION=4.17 +export CONFIG_COREBOOT_VERSION=purism export CONFIG_LINUX_VERSION=5.10.5 export CONFIG_PURISM_BLOBS=y @@ -30,6 +30,8 @@ CONFIG_LINUX_USB=y export CONFIG_TPM=y export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y +export CONFIG_TOTP_SKIP_QRCODE=y +export CONFIG_OEMRESET_OFFER_DEFAULTS=y export CONFIG_BOOTSCRIPT=/bin/gui-init export CONFIG_BOOT_REQ_HASH=n export CONFIG_BOOT_REQ_ROLLBACK=n @@ -39,3 +41,6 @@ export CONFIG_BOOT_DEV="/dev/nvme0n1p1" export CONFIG_BOARD_NAME="Librem 13 v2/v3" export CONFIG_FLASHROM_OPTIONS="-p internal" export CONFIG_AUTO_BOOT_TIMEOUT=5 +export CONFIG_ROOT_DEV="/dev/nvme0n1p2" +export CONFIG_ROOT_DIRLIST="bin boot lib sbin usr" +export CONFIG_ROOT_CHECK_AT_BOOT="n" diff --git a/boards/librem_13v4/librem_13v4.config b/boards/librem_13v4/librem_13v4.config index 766958e13..45775daf5 100644 --- a/boards/librem_13v4/librem_13v4.config +++ b/boards/librem_13v4/librem_13v4.config @@ -3,7 +3,7 @@ CONFIG_LINUX_CONFIG=config/linux-librem_common.config CONFIG_COREBOOT_CONFIG=config/coreboot-librem_13v4.config export CONFIG_COREBOOT=y -export CONFIG_COREBOOT_VERSION=4.17 +export CONFIG_COREBOOT_VERSION=purism export CONFIG_LINUX_VERSION=5.10.5 export CONFIG_PURISM_BLOBS=y @@ -30,6 +30,8 @@ CONFIG_LINUX_USB=y export CONFIG_TPM=y export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y +export CONFIG_TOTP_SKIP_QRCODE=y +export CONFIG_OEMRESET_OFFER_DEFAULTS=y export CONFIG_BOOTSCRIPT=/bin/gui-init export CONFIG_BOOT_REQ_HASH=n export CONFIG_BOOT_REQ_ROLLBACK=n @@ -39,3 +41,6 @@ export CONFIG_BOOT_DEV="/dev/nvme0n1p1" export CONFIG_BOARD_NAME="Librem 13 v4" export CONFIG_FLASHROM_OPTIONS="-p internal" export CONFIG_AUTO_BOOT_TIMEOUT=5 +export CONFIG_ROOT_DEV="/dev/nvme0n1p2" +export CONFIG_ROOT_DIRLIST="bin boot lib sbin usr" +export CONFIG_ROOT_CHECK_AT_BOOT="n" diff --git a/boards/librem_14/librem_14.config b/boards/librem_14/librem_14.config index 324fb5432..bba19ab91 100644 --- a/boards/librem_14/librem_14.config +++ b/boards/librem_14/librem_14.config @@ -3,7 +3,7 @@ CONFIG_LINUX_CONFIG=config/linux-librem_common.config CONFIG_COREBOOT_CONFIG=config/coreboot-librem_14.config export CONFIG_COREBOOT=y -export CONFIG_COREBOOT_VERSION=4.17 +export CONFIG_COREBOOT_VERSION=purism export CONFIG_LINUX_VERSION=5.10.5 export CONFIG_PURISM_BLOBS=y @@ -28,6 +28,8 @@ CONFIG_LINUX_USB=y export CONFIG_TPM=y export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y +export CONFIG_TOTP_SKIP_QRCODE=y +export CONFIG_OEMRESET_OFFER_DEFAULTS=y export CONFIG_BOOTSCRIPT=/bin/gui-init export CONFIG_BOOT_REQ_HASH=n @@ -39,3 +41,6 @@ export CONFIG_BOARD_NAME="Librem 14" export CONFIG_FLASHROM_OPTIONS="-p internal" export CONFIG_AUTO_BOOT_TIMEOUT=5 +export CONFIG_ROOT_DEV="/dev/nvme0n1p2" +export CONFIG_ROOT_DIRLIST="bin boot lib sbin usr" +export CONFIG_ROOT_CHECK_AT_BOOT="n" diff --git a/boards/librem_15v3/librem_15v3.config b/boards/librem_15v3/librem_15v3.config index 1b4522f5a..b914d9bd8 100644 --- a/boards/librem_15v3/librem_15v3.config +++ b/boards/librem_15v3/librem_15v3.config @@ -3,7 +3,7 @@ CONFIG_LINUX_CONFIG=config/linux-librem_common.config CONFIG_COREBOOT_CONFIG=config/coreboot-librem_15v3.config export CONFIG_COREBOOT=y -export CONFIG_COREBOOT_VERSION=4.17 +export CONFIG_COREBOOT_VERSION=purism export CONFIG_LINUX_VERSION=5.10.5 export CONFIG_PURISM_BLOBS=y @@ -30,6 +30,8 @@ CONFIG_LINUX_USB=y export CONFIG_TPM=y export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y +export CONFIG_TOTP_SKIP_QRCODE=y +export CONFIG_OEMRESET_OFFER_DEFAULTS=y export CONFIG_BOOTSCRIPT=/bin/gui-init export CONFIG_BOOT_REQ_HASH=n export CONFIG_BOOT_REQ_ROLLBACK=n @@ -39,3 +41,6 @@ export CONFIG_BOOT_DEV="/dev/nvme0n1p1" export CONFIG_BOARD_NAME="Librem 15 v3" export CONFIG_FLASHROM_OPTIONS="-p internal" export CONFIG_AUTO_BOOT_TIMEOUT=5 +export CONFIG_ROOT_DEV="/dev/nvme0n1p2" +export CONFIG_ROOT_DIRLIST="bin boot lib sbin usr" +export CONFIG_ROOT_CHECK_AT_BOOT="n" diff --git a/boards/librem_15v4/librem_15v4.config b/boards/librem_15v4/librem_15v4.config index b5a1b8d81..28fbe5cba 100644 --- a/boards/librem_15v4/librem_15v4.config +++ b/boards/librem_15v4/librem_15v4.config @@ -3,7 +3,7 @@ CONFIG_LINUX_CONFIG=config/linux-librem_common.config CONFIG_COREBOOT_CONFIG=config/coreboot-librem_15v4.config export CONFIG_COREBOOT=y -export CONFIG_COREBOOT_VERSION=4.17 +export CONFIG_COREBOOT_VERSION=purism export CONFIG_LINUX_VERSION=5.10.5 export CONFIG_PURISM_BLOBS=y @@ -30,6 +30,8 @@ CONFIG_LINUX_USB=y export CONFIG_TPM=y export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y +export CONFIG_TOTP_SKIP_QRCODE=y +export CONFIG_OEMRESET_OFFER_DEFAULTS=y export CONFIG_BOOTSCRIPT=/bin/gui-init export CONFIG_BOOT_REQ_HASH=n export CONFIG_BOOT_REQ_ROLLBACK=n @@ -39,3 +41,6 @@ export CONFIG_BOOT_DEV="/dev/nvme0n1p1" export CONFIG_BOARD_NAME="Librem 15 v4" export CONFIG_FLASHROM_OPTIONS="-p internal" export CONFIG_AUTO_BOOT_TIMEOUT=5 +export CONFIG_ROOT_DEV="/dev/nvme0n1p2" +export CONFIG_ROOT_DIRLIST="bin boot lib sbin usr" +export CONFIG_ROOT_CHECK_AT_BOOT="n" diff --git a/boards/librem_l1um/librem_l1um.config b/boards/librem_l1um/librem_l1um.config index dd60686a6..69052e1e0 100644 --- a/boards/librem_l1um/librem_l1um.config +++ b/boards/librem_l1um/librem_l1um.config @@ -28,6 +28,8 @@ CONFIG_LINUX_USB=y export CONFIG_TPM=y export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y +export CONFIG_TOTP_SKIP_QRCODE=y +export CONFIG_OEMRESET_OFFER_DEFAULTS=y export CONFIG_BOOTSCRIPT=/bin/gui-init export CONFIG_BOOT_REQ_HASH=n @@ -39,3 +41,6 @@ export CONFIG_BOARD_NAME="Librem Server L1UM" export CONFIG_AUTO_BOOT_TIMEOUT=5 export CONFIG_FLASHROM_OPTIONS="-p internal" export CONFIG_USB_KEYBOARD=y +export CONFIG_ROOT_DEV="/dev/nvme0n1p2" +export CONFIG_ROOT_DIRLIST="bin boot lib sbin usr" +export CONFIG_ROOT_CHECK_AT_BOOT="n" diff --git a/boards/librem_l1um_v2/librem_l1um_v2.config b/boards/librem_l1um_v2/librem_l1um_v2.config new file mode 100644 index 000000000..103714874 --- /dev/null +++ b/boards/librem_l1um_v2/librem_l1um_v2.config @@ -0,0 +1,51 @@ +# Configuration for librem_l1um_v2 +CONFIG_LINUX_CONFIG=config/linux-librem_common-6.1.8.config +CONFIG_COREBOOT_CONFIG=config/coreboot-librem_l1um_v2.config + +export CONFIG_COREBOOT=y +export CONFIG_COREBOOT_VERSION=purism +export CONFIG_LINUX_VERSION=6.1.8 +export CONFIG_PURISM_BLOBS=y + +CONFIG_CRYPTSETUP2=y +CONFIG_FLASHROM=y +CONFIG_FLASHTOOLS=y +CONFIG_GPG2=y +CONFIG_KEXEC=y +CONFIG_UTIL_LINUX=y +CONFIG_LVM2=y +CONFIG_MBEDTLS=y +CONFIG_PCIUTILS=y +CONFIG_POPT=y +CONFIG_QRENCODE=y +CONFIG_TPMTOTP=y + +CONFIG_CAIRO=y +CONFIG_FBWHIPTAIL=y +CONFIG_HOTPKEY=y + +CONFIG_LINUX_USB=y + +export CONFIG_TPM=y +export CONFIG_TPM2_TOOLS=y +CONFIG_TPM2_TSS=y +CONFIG_OPENSSL=y +CONFIG_PRIMARY_KEY_TYPE=ecc +export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y +export CONFIG_TOTP_SKIP_QRCODE=y +export CONFIG_OEMRESET_OFFER_DEFAULTS=y + +export CONFIG_BOOTSCRIPT=/bin/gui-init +export CONFIG_BOOT_REQ_HASH=n +export CONFIG_BOOT_REQ_ROLLBACK=n +export CONFIG_BOOT_KERNEL_ADD="intel_iommu=on" +export CONFIG_BOOT_KERNEL_REMOVE="plymouth.ignore-serial-consoles" +export CONFIG_BOOT_RECOVERY_SERIAL="/dev/ttyS0" +export CONFIG_BOOT_DEV="/dev/nvme0n1p1" +export CONFIG_BOARD_NAME="Librem Server L1UM v2" +export CONFIG_AUTO_BOOT_TIMEOUT=5 +export CONFIG_FLASHROM_OPTIONS="-p internal" +export CONFIG_USB_KEYBOARD=y +export CONFIG_ROOT_DEV="/dev/nvme0n1p2" +export CONFIG_ROOT_DIRLIST="bin boot lib sbin usr" +export CONFIG_ROOT_CHECK_AT_BOOT="n" diff --git a/boards/librem_mini/initrd/bin/board-init.sh b/boards/librem_mini/initrd/bin/board-init.sh new file mode 100755 index 000000000..4299016c7 --- /dev/null +++ b/boards/librem_mini/initrd/bin/board-init.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -o pipefail + +. /tmp/config + +# If CONFIG_AUTOMATIC_POWERON is set, always set the EC BRAM setting during +# boot. It persists as long as the RTC battery is set, but set it during every +# boot for robustness in case the battery is temporarily removed, or the user +# toggles in config-gui and then does not flash, etc. +if [ "$CONFIG_AUTOMATIC_POWERON" = "y" ]; then + set_ec_poweron.sh y +fi + +# Don't disable the setting in the EC BRAM though if CONFIG_AUTOMATIC_POWERON +# is not enabled. The default is disabled anyway, and the OS could configure +# it. diff --git a/boards/librem_mini/initrd/bin/set_ec_poweron.sh b/boards/librem_mini/initrd/bin/set_ec_poweron.sh new file mode 100755 index 000000000..cbbf0022f --- /dev/null +++ b/boards/librem_mini/initrd/bin/set_ec_poweron.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# Set the EC BRAM setting for automatic power-on. +# If $1 is 'y', enable automatic power-on. Otherwise, disable it. + +# EC BRAM bank 1 +BRAMADDR=0x360 +BRAMDATA=0x361 + +outb "$BRAMADDR" 0x29 # Select byte at offset 29h +if [ "$1" = "y" ]; then + outb "$BRAMDATA" 0x00 # 0 -> automatic power-on +else + outb "$BRAMDATA" 0x01 # 1 -> stay off +fi + diff --git a/boards/librem_mini/librem_mini.config b/boards/librem_mini/librem_mini.config index 60f8c5014..e438c27d6 100644 --- a/boards/librem_mini/librem_mini.config +++ b/boards/librem_mini/librem_mini.config @@ -3,7 +3,7 @@ CONFIG_LINUX_CONFIG=config/linux-librem_common.config CONFIG_COREBOOT_CONFIG=config/coreboot-librem_mini.config export CONFIG_COREBOOT=y -export CONFIG_COREBOOT_VERSION=4.17 +export CONFIG_COREBOOT_VERSION=purism export CONFIG_LINUX_VERSION=5.10.5 export CONFIG_PURISM_BLOBS=y @@ -11,6 +11,7 @@ CONFIG_CRYPTSETUP2=y CONFIG_FLASHROM=y CONFIG_FLASHTOOLS=y CONFIG_GPG2=y +CONFIG_IOPORT=y CONFIG_KEXEC=y CONFIG_UTIL_LINUX=y CONFIG_LVM2=y @@ -28,6 +29,8 @@ CONFIG_LINUX_USB=y export CONFIG_TPM=n export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y +export CONFIG_TOTP_SKIP_QRCODE=y +export CONFIG_OEMRESET_OFFER_DEFAULTS=y export CONFIG_BOOTSCRIPT=/bin/gui-init export CONFIG_BOOT_REQ_HASH=n @@ -39,3 +42,7 @@ export CONFIG_BOARD_NAME="Librem Mini" export CONFIG_FLASHROM_OPTIONS="-p internal" export CONFIG_USB_KEYBOARD=y export CONFIG_AUTO_BOOT_TIMEOUT=5 +export CONFIG_ROOT_DEV="/dev/nvme0n1p2" +export CONFIG_ROOT_DIRLIST="bin boot lib sbin usr" +export CONFIG_ROOT_CHECK_AT_BOOT="n" +export CONFIG_SUPPORT_AUTOMATIC_POWERON=y diff --git a/boards/librem_mini_v2/initrd/bin/board-init.sh b/boards/librem_mini_v2/initrd/bin/board-init.sh new file mode 100755 index 000000000..4299016c7 --- /dev/null +++ b/boards/librem_mini_v2/initrd/bin/board-init.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -o pipefail + +. /tmp/config + +# If CONFIG_AUTOMATIC_POWERON is set, always set the EC BRAM setting during +# boot. It persists as long as the RTC battery is set, but set it during every +# boot for robustness in case the battery is temporarily removed, or the user +# toggles in config-gui and then does not flash, etc. +if [ "$CONFIG_AUTOMATIC_POWERON" = "y" ]; then + set_ec_poweron.sh y +fi + +# Don't disable the setting in the EC BRAM though if CONFIG_AUTOMATIC_POWERON +# is not enabled. The default is disabled anyway, and the OS could configure +# it. diff --git a/boards/librem_mini_v2/initrd/bin/set_ec_poweron.sh b/boards/librem_mini_v2/initrd/bin/set_ec_poweron.sh new file mode 100755 index 000000000..cbbf0022f --- /dev/null +++ b/boards/librem_mini_v2/initrd/bin/set_ec_poweron.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# Set the EC BRAM setting for automatic power-on. +# If $1 is 'y', enable automatic power-on. Otherwise, disable it. + +# EC BRAM bank 1 +BRAMADDR=0x360 +BRAMDATA=0x361 + +outb "$BRAMADDR" 0x29 # Select byte at offset 29h +if [ "$1" = "y" ]; then + outb "$BRAMDATA" 0x00 # 0 -> automatic power-on +else + outb "$BRAMDATA" 0x01 # 1 -> stay off +fi + diff --git a/boards/librem_mini_v2/librem_mini_v2.config b/boards/librem_mini_v2/librem_mini_v2.config index c51dd05bc..30878ad0b 100644 --- a/boards/librem_mini_v2/librem_mini_v2.config +++ b/boards/librem_mini_v2/librem_mini_v2.config @@ -3,7 +3,7 @@ CONFIG_LINUX_CONFIG=config/linux-librem_common.config CONFIG_COREBOOT_CONFIG=config/coreboot-librem_mini_v2.config export CONFIG_COREBOOT=y -export CONFIG_COREBOOT_VERSION=4.17 +export CONFIG_COREBOOT_VERSION=purism export CONFIG_LINUX_VERSION=5.10.5 export CONFIG_PURISM_BLOBS=y @@ -11,6 +11,7 @@ CONFIG_CRYPTSETUP2=y CONFIG_FLASHROM=y CONFIG_FLASHTOOLS=y CONFIG_GPG2=y +CONFIG_IOPORT=y CONFIG_KEXEC=y CONFIG_UTIL_LINUX=y CONFIG_LVM2=y @@ -19,6 +20,8 @@ CONFIG_PCIUTILS=y CONFIG_POPT=y CONFIG_QRENCODE=y CONFIG_TPMTOTP=y +# zstd-decompress - for blob jail, needed to extract /init from zstd cpio archive +CONFIG_ZSTD=y CONFIG_CAIRO=y CONFIG_FBWHIPTAIL=y @@ -28,6 +31,8 @@ CONFIG_LINUX_USB=y export CONFIG_TPM=n export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y +export CONFIG_TOTP_SKIP_QRCODE=y +export CONFIG_OEMRESET_OFFER_DEFAULTS=y export CONFIG_BOOTSCRIPT=/bin/gui-init export CONFIG_BOOT_REQ_HASH=n @@ -39,3 +44,7 @@ export CONFIG_BOARD_NAME="Librem Mini v2" export CONFIG_FLASHROM_OPTIONS="-p internal" export CONFIG_USB_KEYBOARD=y export CONFIG_AUTO_BOOT_TIMEOUT=5 +export CONFIG_ROOT_DEV="/dev/nvme0n1p2" +export CONFIG_ROOT_DIRLIST="bin boot lib sbin usr" +export CONFIG_ROOT_CHECK_AT_BOOT="n" +export CONFIG_SUPPORT_AUTOMATIC_POWERON=y diff --git a/boards/qemu-coreboot-fbwhiptail-tpm1-hotp/qemu-coreboot-fbwhiptail-tpm1-hotp.config b/boards/qemu-coreboot-fbwhiptail-tpm1-hotp/qemu-coreboot-fbwhiptail-tpm1-hotp.config index c2a9e5f04..94285c005 100644 --- a/boards/qemu-coreboot-fbwhiptail-tpm1-hotp/qemu-coreboot-fbwhiptail-tpm1-hotp.config +++ b/boards/qemu-coreboot-fbwhiptail-tpm1-hotp/qemu-coreboot-fbwhiptail-tpm1-hotp.config @@ -8,6 +8,10 @@ export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=4.19 export CONFIG_LINUX_VERSION=5.10.5 +#Enable only one RESTRICTED/BASIC boot modes below to test them manually (we cannot inject config under QEMU (no internal flashing) +#export CONFIG_RESTRICTED_BOOT=y +#export CONFIG_BASIC_BOOT=y + #Enable DEBUG output export CONFIG_DEBUG_OUTPUT=y export CONFIG_ENABLE_FUNCTION_TRACING_OUTPUT=y diff --git a/boards/qemu-coreboot-fbwhiptail-tpm1/qemu-coreboot-fbwhiptail-tpm1.config b/boards/qemu-coreboot-fbwhiptail-tpm1/qemu-coreboot-fbwhiptail-tpm1.config index c85d304b8..c70213f3d 100644 --- a/boards/qemu-coreboot-fbwhiptail-tpm1/qemu-coreboot-fbwhiptail-tpm1.config +++ b/boards/qemu-coreboot-fbwhiptail-tpm1/qemu-coreboot-fbwhiptail-tpm1.config @@ -6,6 +6,10 @@ export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=4.19 export CONFIG_LINUX_VERSION=5.10.5 +#Enable only one RESTRICTED/BASIC boot modes below to test them manually (we cannot inject config under QEMU (no internal flashing) +#export CONFIG_RESTRICTED_BOOT=y +#export CONFIG_BASIC_BOOT=y + #Enable DEBUG output export CONFIG_DEBUG_OUTPUT=y export CONFIG_ENABLE_FUNCTION_TRACING_OUTPUT=y diff --git a/boards/qemu-coreboot-fbwhiptail-tpm2-hotp/qemu-coreboot-fbwhiptail-tpm2-hotp.config b/boards/qemu-coreboot-fbwhiptail-tpm2-hotp/qemu-coreboot-fbwhiptail-tpm2-hotp.config index 5a5aa8a43..425d513ea 100644 --- a/boards/qemu-coreboot-fbwhiptail-tpm2-hotp/qemu-coreboot-fbwhiptail-tpm2-hotp.config +++ b/boards/qemu-coreboot-fbwhiptail-tpm2-hotp/qemu-coreboot-fbwhiptail-tpm2-hotp.config @@ -7,6 +7,10 @@ export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=4.19 export CONFIG_LINUX_VERSION=5.10.5 +#Enable only one RESTRICTED/BASIC boot modes below to test them manually (we cannot inject config under QEMU (no internal flashing) +#export CONFIG_RESTRICTED_BOOT=y +#export CONFIG_BASIC_BOOT=y + #Enable DEBUG output export CONFIG_DEBUG_OUTPUT=y export CONFIG_ENABLE_FUNCTION_TRACING_OUTPUT=y diff --git a/boards/qemu-coreboot-fbwhiptail-tpm2/qemu-coreboot-fbwhiptail-tpm2.config b/boards/qemu-coreboot-fbwhiptail-tpm2/qemu-coreboot-fbwhiptail-tpm2.config index d5921c7f5..adc976845 100644 --- a/boards/qemu-coreboot-fbwhiptail-tpm2/qemu-coreboot-fbwhiptail-tpm2.config +++ b/boards/qemu-coreboot-fbwhiptail-tpm2/qemu-coreboot-fbwhiptail-tpm2.config @@ -6,6 +6,10 @@ export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=4.19 export CONFIG_LINUX_VERSION=5.10.5 +#Enable only one RESTRICTED/BASIC boot modes below to test them manually (we cannot inject config under QEMU (no internal flashing) +#export CONFIG_RESTRICTED_BOOT=y +#export CONFIG_BASIC_BOOT=y + #Enable DEBUG output export CONFIG_DEBUG_OUTPUT=y export CONFIG_ENABLE_FUNCTION_TRACING_OUTPUT=y diff --git a/boards/qemu-coreboot-whiptail-tpm1-hotp/qemu-coreboot-whiptail-tpm1-hotp.config b/boards/qemu-coreboot-whiptail-tpm1-hotp/qemu-coreboot-whiptail-tpm1-hotp.config index 358dc5d6c..cae5d98fc 100644 --- a/boards/qemu-coreboot-whiptail-tpm1-hotp/qemu-coreboot-whiptail-tpm1-hotp.config +++ b/boards/qemu-coreboot-whiptail-tpm1-hotp/qemu-coreboot-whiptail-tpm1-hotp.config @@ -8,6 +8,10 @@ export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=4.19 export CONFIG_LINUX_VERSION=5.10.5 +#Enable only one RESTRICTED/BASIC boot modes below to test them manually (we cannot inject config under QEMU (no internal flashing) +#export CONFIG_RESTRICTED_BOOT=y +#export CONFIG_BASIC_BOOT=y + #Enable DEBUG output export CONFIG_DEBUG_OUTPUT=y export CONFIG_ENABLE_FUNCTION_TRACING_OUTPUT=y diff --git a/boards/qemu-coreboot-whiptail-tpm1/qemu-coreboot-whiptail-tpm1.config b/boards/qemu-coreboot-whiptail-tpm1/qemu-coreboot-whiptail-tpm1.config index 37dbdb6c6..b65a2381b 100644 --- a/boards/qemu-coreboot-whiptail-tpm1/qemu-coreboot-whiptail-tpm1.config +++ b/boards/qemu-coreboot-whiptail-tpm1/qemu-coreboot-whiptail-tpm1.config @@ -6,6 +6,10 @@ export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=4.19 export CONFIG_LINUX_VERSION=5.10.5 +#Enable only one RESTRICTED/BASIC boot modes below to test them manually (we cannot inject config under QEMU (no internal flashing) +#export CONFIG_RESTRICTED_BOOT=y +#export CONFIG_BASIC_BOOT=y + #Enable DEBUG output export CONFIG_DEBUG_OUTPUT=y export CONFIG_ENABLE_FUNCTION_TRACING_OUTPUT=y diff --git a/boards/qemu-coreboot-whiptail-tpm2-hotp/qemu-coreboot-whiptail-tpm2-hotp.config b/boards/qemu-coreboot-whiptail-tpm2-hotp/qemu-coreboot-whiptail-tpm2-hotp.config index 2b595eaae..2941c80b1 100644 --- a/boards/qemu-coreboot-whiptail-tpm2-hotp/qemu-coreboot-whiptail-tpm2-hotp.config +++ b/boards/qemu-coreboot-whiptail-tpm2-hotp/qemu-coreboot-whiptail-tpm2-hotp.config @@ -7,6 +7,10 @@ export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=4.19 export CONFIG_LINUX_VERSION=5.10.5 +#Enable only one RESTRICTED/BASIC boot modes below to test them manually (we cannot inject config under QEMU (no internal flashing) +#export CONFIG_RESTRICTED_BOOT=y +#export CONFIG_BASIC_BOOT=y + #Enable DEBUG output export CONFIG_DEBUG_OUTPUT=y export CONFIG_ENABLE_FUNCTION_TRACING_OUTPUT=y diff --git a/boards/qemu-coreboot-whiptail-tpm2/qemu-coreboot-whiptail-tpm2.config b/boards/qemu-coreboot-whiptail-tpm2/qemu-coreboot-whiptail-tpm2.config index 142cfb5ad..087e798a3 100644 --- a/boards/qemu-coreboot-whiptail-tpm2/qemu-coreboot-whiptail-tpm2.config +++ b/boards/qemu-coreboot-whiptail-tpm2/qemu-coreboot-whiptail-tpm2.config @@ -6,6 +6,10 @@ export CONFIG_COREBOOT=y export CONFIG_COREBOOT_VERSION=4.19 export CONFIG_LINUX_VERSION=5.10.5 +#Enable only one RESTRICTED/BASIC boot modes below to test them manually (we cannot inject config under QEMU (no internal flashing) +#export CONFIG_RESTRICTED_BOOT=y +#export CONFIG_BASIC_BOOT=y + #Enable DEBUG output export CONFIG_DEBUG_OUTPUT=y export CONFIG_ENABLE_FUNCTION_TRACING_OUTPUT=y diff --git a/config/busybox.config b/config/busybox.config index 23c8fd3fd..c5891f256 100644 --- a/config/busybox.config +++ b/config/busybox.config @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Busybox version: 1.33.2 -# Fri Jan 7 12:33:00 2022 +# Mon Jul 3 16:24:44 2023 # CONFIG_HAVE_DOT_CONFIG=y @@ -150,9 +150,9 @@ CONFIG_ZCAT=y CONFIG_FEATURE_GUNZIP_LONG_OPTIONS=y CONFIG_BUNZIP2=y CONFIG_BZCAT=y -# CONFIG_UNLZMA is not set -# CONFIG_LZCAT is not set -# CONFIG_LZMA is not set +CONFIG_UNLZMA=y +CONFIG_LZCAT=y +CONFIG_LZMA=y CONFIG_UNXZ=y CONFIG_XZCAT=y CONFIG_XZ=y @@ -192,7 +192,7 @@ CONFIG_FEATURE_UNZIP_CDF=y # CONFIG_FEATURE_UNZIP_BZIP2 is not set # CONFIG_FEATURE_UNZIP_LZMA is not set # CONFIG_FEATURE_UNZIP_XZ is not set -# CONFIG_FEATURE_LZMA_FAST is not set +CONFIG_FEATURE_LZMA_FAST=y # # Coreutils @@ -322,7 +322,7 @@ CONFIG_TR=y CONFIG_FEATURE_TR_CLASSES=y CONFIG_FEATURE_TR_EQUIV=y CONFIG_TRUE=y -# CONFIG_TRUNCATE is not set +CONFIG_TRUNCATE=y CONFIG_TTY=y CONFIG_UNAME=y CONFIG_UNAME_OSNAME="GNU/Linux" @@ -332,7 +332,7 @@ CONFIG_UNIQ=y CONFIG_USLEEP=y # CONFIG_UUDECODE is not set CONFIG_BASE32=y -CONFIG_BASE64=n +# CONFIG_BASE64 is not set # CONFIG_UUENCODE is not set CONFIG_WC=y CONFIG_FEATURE_WC_LARGE=y @@ -1103,7 +1103,7 @@ CONFIG_SH_IS_ASH=y # CONFIG_SH_IS_NONE is not set # CONFIG_BASH_IS_ASH is not set # CONFIG_BASH_IS_HUSH is not set -# CONFIG_BASH_IS_NONE is not set +CONFIG_BASH_IS_NONE=y CONFIG_SHELL_ASH=y CONFIG_ASH=y CONFIG_ASH_OPTIMIZE_FOR_SIZE=y diff --git a/config/coreboot-librem_14.config b/config/coreboot-librem_14.config index 871a9afd6..5bfa98de2 100644 --- a/config/coreboot-librem_14.config +++ b/config/coreboot-librem_14.config @@ -12,3 +12,4 @@ CONFIG_PAYLOAD_LINUX=y CONFIG_PAYLOAD_FILE="@BOARD_BUILD_DIR@/bzImage" CONFIG_LINUX_INITRD="@BOARD_BUILD_DIR@/initrd.cpio.xz" CONFIG_LINUX_COMMAND_LINE="intel_iommu=igfx_off quiet loglevel=2 drm_kms_helper.drm_leak_fbdev_smem=1 i915.enable_fbc=0" +CONFIG_CBFS_SIZE=0xC00000 diff --git a/config/coreboot-librem_l1um_v2.config b/config/coreboot-librem_l1um_v2.config new file mode 100644 index 000000000..f5d208f48 --- /dev/null +++ b/config/coreboot-librem_l1um_v2.config @@ -0,0 +1,16 @@ +CONFIG_VENDOR_PURISM=y +CONFIG_CBFS_SIZE=0x1000000 +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_IFD_BIN_PATH="3rdparty/purism-blobs/mainboard/purism/librem_l1um_v2/flashdescriptor.bin" +CONFIG_ME_BIN_PATH="3rdparty/purism-blobs/mainboard/purism/librem_l1um_v2/me.bin" +CONFIG_HAVE_IFD_BIN=y +CONFIG_BOARD_PURISM_LIBREM_L1UM_V2=y +CONFIG_TPM_MEASURED_BOOT=y +CONFIG_LINUX_COMMAND_LINE="quiet loglevel=2" +CONFIG_CPU_MICROCODE_CBFS_EXTERNAL_BINS=y +CONFIG_CPU_UCODE_BINARIES="3rdparty/purism-blobs/mainboard/purism/librem_l1um_v2/cpu_microcode_blob.bin" +CONFIG_HAVE_ME_BIN=y +CONFIG_NO_GFX_INIT=y +CONFIG_PAYLOAD_LINUX=y +CONFIG_PAYLOAD_FILE="@BOARD_BUILD_DIR@/bzImage" +CONFIG_LINUX_INITRD="@BOARD_BUILD_DIR@/initrd.cpio.xz" diff --git a/config/coreboot-librem_mini_v2.config b/config/coreboot-librem_mini_v2.config index 849851694..fa6689b92 100644 --- a/config/coreboot-librem_mini_v2.config +++ b/config/coreboot-librem_mini_v2.config @@ -12,3 +12,4 @@ CONFIG_PAYLOAD_LINUX=y CONFIG_PAYLOAD_FILE="@BOARD_BUILD_DIR@/bzImage" CONFIG_LINUX_INITRD="@BOARD_BUILD_DIR@/initrd.cpio.xz" CONFIG_LINUX_COMMAND_LINE="intel_iommu=igfx_off quiet loglevel=2 drm_kms_helper.drm_leak_fbdev_smem=1 i915.enable_fbc=0" +CONFIG_CBFS_SIZE=0xC00000 diff --git a/config/linux-librem_common-6.1.8.config b/config/linux-librem_common-6.1.8.config new file mode 100644 index 000000000..20564d0b1 --- /dev/null +++ b/config/linux-librem_common-6.1.8.config @@ -0,0 +1,293 @@ +CONFIG_LOCALVERSION="-@BRAND_NAME@" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_KERNEL_XZ=y +# CONFIG_CROSS_MEMORY_ATTACH is not set +CONFIG_NO_HZ_IDLE=y +CONFIG_PREEMPT_VOLUNTARY=y +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="@BLOB_DIR@/dev.cpio" +# CONFIG_RD_GZIP is not set +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_LZ4 is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_SGETMASK_SYSCALL is not set +# CONFIG_SYSFS_SYSCALL is not set +# CONFIG_FHANDLE is not set +# CONFIG_BASE_FULL is not set +# CONFIG_SIGNALFD is not set +# CONFIG_TIMERFD is not set +# CONFIG_EVENTFD is not set +# CONFIG_AIO is not set +# CONFIG_ADVISE_SYSCALLS is not set +CONFIG_EMBEDDED=y +CONFIG_SMP=y +# CONFIG_X86_EXTENDED_PLATFORM is not set +CONFIG_PROCESSOR_SELECT=y +# CONFIG_CPU_SUP_CENTAUR is not set +CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y +# CONFIG_X86_MCE_AMD is not set +# CONFIG_PERF_EVENTS_INTEL_RAPL is not set +# CONFIG_MICROCODE is not set +CONFIG_X86_PMEM_LEGACY=y +# CONFIG_MTRR is not set +# CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS is not set +CONFIG_KEXEC=y +CONFIG_KEXEC_FILE=y +# CONFIG_RELOCATABLE is not set +CONFIG_PHYSICAL_ALIGN=0x1000000 +# CONFIG_MODIFY_LDT_SYSCALL is not set +# CONFIG_RETPOLINE is not set +# CONFIG_SUSPEND is not set +# CONFIG_VIRTUALIZATION is not set +CONFIG_JUMP_LABEL=y +# CONFIG_SECCOMP is not set +CONFIG_MODULES=y +# CONFIG_COREDUMP is not set +# CONFIG_SWAP is not set +# CONFIG_COMPAT_BRK is not set +# CONFIG_COMPACTION is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 +# CONFIG_VM_EVENT_COUNTERS is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_SYN_COOKIES=y +# CONFIG_INET_DIAG is not set +# CONFIG_IPV6 is not set +# CONFIG_WIRELESS is not set +CONFIG_PCI=y +CONFIG_PCI_MSI=y +CONFIG_PCI_IOV=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_STANDALONE is not set +# CONFIG_ALLOW_DEV_COREDUMP is not set +# CONFIG_FIRMWARE_MEMMAP is not set +# CONFIG_DMIID is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=65536 +CONFIG_BLK_DEV_NVME=y +CONFIG_EEPROM_93CX6=m +CONFIG_INTEL_MEI_ME=m +CONFIG_INTEL_MEI_TXE=m +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_DEV_SR=y +CONFIG_CHR_DEV_SG=y +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_ISCSI_TCP=y +CONFIG_ATA=y +CONFIG_SATA_AHCI=y +# CONFIG_ATA_SFF is not set +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_NETDEVICES=y +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NET_VENDOR_ADAPTEC is not set +# CONFIG_NET_VENDOR_AGERE is not set +# CONFIG_NET_VENDOR_ALTEON is not set +# CONFIG_NET_VENDOR_AMAZON is not set +# CONFIG_NET_VENDOR_AMD is not set +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_VENDOR_ATHEROS is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CAVIUM is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_NET_VENDOR_CISCO is not set +# CONFIG_NET_VENDOR_DEC is not set +# CONFIG_NET_VENDOR_DLINK is not set +# CONFIG_NET_VENDOR_EMULEX is not set +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_I825XX is not set +CONFIG_E1000=m +CONFIG_E1000E=m +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MELLANOX is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MYRI is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETRONOME is not set +# CONFIG_NET_VENDOR_NVIDIA is not set +# CONFIG_NET_VENDOR_OKI is not set +# CONFIG_NET_VENDOR_QLOGIC is not set +# CONFIG_NET_VENDOR_BROCADE is not set +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_RDC is not set +# CONFIG_NET_VENDOR_REALTEK is not set +# CONFIG_NET_VENDOR_RENESAS is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SILAN is not set +# CONFIG_NET_VENDOR_SIS is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SUN is not set +# CONFIG_NET_VENDOR_SYNOPSYS is not set +# CONFIG_NET_VENDOR_TEHUTI is not set +# CONFIG_NET_VENDOR_TI is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_USB_NET_DRIVERS is not set +# CONFIG_WLAN is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_SERIO_SERPORT is not set +# CONFIG_UNIX98_PTYS is not set +# CONFIG_LEGACY_PTYS is not set +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +# CONFIG_SERIAL_8250_PNP is not set +# CONFIG_SERIAL_8250_PCI is not set +# CONFIG_SERIAL_8250_LPSS is not set +# CONFIG_SERIAL_8250_MID is not set +CONFIG_TTY_PRINTK=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_TIMERIOMEM=m +CONFIG_HW_RANDOM_INTEL=m +CONFIG_HW_RANDOM_AMD=m +CONFIG_HW_RANDOM_VIA=m +CONFIG_TCG_TPM=y +CONFIG_TCG_TIS=y +# CONFIG_RANDOM_TRUST_CPU is not set +# CONFIG_RANDOM_TRUST_BOOTLOADER is not set +# CONFIG_I2C_COMPAT is not set +CONFIG_I2C_MUX=m +CONFIG_I2C_MUX_PCA9541=m +CONFIG_I2C_MUX_REG=m +# CONFIG_I2C_HELPER_AUTO is not set +CONFIG_I2C_SLAVE=y +# CONFIG_HWMON is not set +# CONFIG_X86_PKG_TEMP_THERMAL is not set +CONFIG_MFD_SYSCON=y +CONFIG_DRM=y +CONFIG_DRM_I915=y +CONFIG_DRM_AST=y +CONFIG_FB=y +CONFIG_FB_VESA=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION=y +CONFIG_USB_HID=m +CONFIG_USB=y +CONFIG_USB_XHCI_HCD=m +CONFIG_USB_XHCI_PLATFORM=m +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_HCD_PLATFORM=m +CONFIG_USB_STORAGE=m +CONFIG_RTC_CLASS=y +CONFIG_COMMON_CLK=y +CONFIG_INTEL_IOMMU=y +CONFIG_INTEL_IOMMU_SVM=y +# CONFIG_INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON is not set +CONFIG_GENERIC_PHY=y +# CONFIG_BLK_DEV_PMEM is not set +# CONFIG_BTT is not set +CONFIG_EXT4_FS=y +# CONFIG_DNOTIFY is not set +# CONFIG_INOTIFY_USER is not set +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +# CONFIG_PROC_SYSCTL is not set +# CONFIG_PROC_PAGE_MONITOR is not set +# CONFIG_MISC_FILESYSTEMS is not set +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_UTF8=y +CONFIG_HARDENED_USERCOPY=y +CONFIG_LSM="lockdown,yama,loadpin,safesetid,integrity,bpf" +CONFIG_CRYPTO_USER=y +CONFIG_CRYPTO_RSA=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_CAMELLIA=m +CONFIG_CRYPTO_FCRYPT=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_SEED=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_CTS=m +CONFIG_CRYPTO_KEYWRAP=m +CONFIG_CRYPTO_LRW=y +CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_XTS=y +CONFIG_CRYPTO_CHACHA20POLY1305=m +CONFIG_CRYPTO_CCM=m +CONFIG_CRYPTO_GCM=m +CONFIG_CRYPTO_CMAC=m +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_VMAC=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_CRC32=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_842=m +CONFIG_CRYPTO_LZ4=m +CONFIG_CRYPTO_LZ4HC=m +CONFIG_CRYPTO_ANSI_CPRNG=m +CONFIG_CRYPTO_USER_API_HASH=y +CONFIG_CRYPTO_USER_API_SKCIPHER=y +CONFIG_CRYPTO_USER_API_RNG=y +CONFIG_CRYPTO_USER_API_AEAD=y +CONFIG_CRYPTO_AES_NI_INTEL=y +CONFIG_CRYPTO_BLOWFISH_X86_64=m +CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64=m +CONFIG_CRYPTO_CAST5_AVX_X86_64=m +CONFIG_CRYPTO_CAST6_AVX_X86_64=m +CONFIG_CRYPTO_DES3_EDE_X86_64=m +CONFIG_CRYPTO_SERPENT_SSE2_X86_64=m +CONFIG_CRYPTO_SERPENT_AVX2_X86_64=m +CONFIG_CRYPTO_TWOFISH_AVX_X86_64=m +CONFIG_CRYPTO_CHACHA20_X86_64=m +CONFIG_CRYPTO_POLY1305_X86_64=m +CONFIG_CRYPTO_SHA1_SSSE3=y +CONFIG_CRYPTO_SHA256_SSSE3=y +CONFIG_CRYPTO_SHA512_SSSE3=y +CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m +CONFIG_CRYPTO_CRC32C_INTEL=y +CONFIG_CRYPTO_CRC32_PCLMUL=m +CONFIG_CRYPTO_CRCT10DIF_PCLMUL=m +# CONFIG_CRYPTO_HW is not set +CONFIG_CORDIC=m +CONFIG_CRC_CCITT=m +CONFIG_CRC_T10DIF=y +CONFIG_CRC_ITU_T=m +CONFIG_CRC7=m +CONFIG_LIBCRC32C=m +CONFIG_CRC8=m +CONFIG_XZ_DEC_TEST=m +CONFIG_IRQ_POLL=y +CONFIG_PRINTK_TIME=y +CONFIG_BOOT_PRINTK_DELAY=y +CONFIG_DYNAMIC_DEBUG=y +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_DEBUG_INFO_DWARF4=y +CONFIG_GDB_SCRIPTS=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_FS=y +# CONFIG_SLUB_DEBUG is not set +CONFIG_HARDLOCKUP_DETECTOR=y +CONFIG_WQ_WATCHDOG=y +# CONFIG_SCHED_DEBUG is not set +CONFIG_STACKTRACE=y +# CONFIG_RCU_TRACE is not set +# CONFIG_FTRACE is not set +# CONFIG_STRICT_DEVMEM is not set +# CONFIG_X86_VERBOSE_BOOTUP is not set +CONFIG_IO_DELAY_0XED=y +# CONFIG_X86_DEBUG_FPU is not set diff --git a/config/linux-librem_common.config b/config/linux-librem_common.config index e9fe0c18b..c0a104471 100644 --- a/config/linux-librem_common.config +++ b/config/linux-librem_common.config @@ -21,7 +21,7 @@ CONFIG_THREAD_INFO_IN_TASK=y # CONFIG_INIT_ENV_ARG_LIMIT=32 # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-heads" +CONFIG_LOCALVERSION="-@BRAND_NAME@" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_BUILD_SALT="" CONFIG_HAVE_KERNEL_GZIP=y diff --git a/initrd/bin/basic-autoboot.sh b/initrd/bin/basic-autoboot.sh new file mode 100755 index 000000000..d924affd6 --- /dev/null +++ b/initrd/bin/basic-autoboot.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -o pipefail + +. /etc/functions + +BOOT_MENU_OPTIONS=/tmp/basic-autoboot-options + +scan_boot_options /boot "grub.cfg" "$BOOT_MENU_OPTIONS" +if [ -s "$BOOT_MENU_OPTIONS" ]; then + kexec-boot -b /boot -e "$(head -1 "$BOOT_MENU_OPTIONS")" +fi diff --git a/initrd/bin/config-gui.sh b/initrd/bin/config-gui.sh index 4f6ea91c7..673629bc0 100755 --- a/initrd/bin/config-gui.sh +++ b/initrd/bin/config-gui.sh @@ -7,28 +7,73 @@ set -e -o pipefail TRACE "Under /bin/config-gui.sh" +ROOT_HASH_FILE="/boot/kexec_root_hashes.txt" + param=$1 -while true; do - dynamic_config_options=( - 'b' ' Change the /boot device' - 's' ' Save the current configuration to the running BIOS' \ - 'r' ' Clear GPG key(s) and reset all user settings' \ - ) - if [ "$CONFIG_FINALIZE_PLATFORM_LOCKING_PRESKYLAKE" = "y" ];then - dynamic_config_options+=( - 't' ' Deactivate Platform Locking to permit OS write access to firmware' - ) +# Read the current ROM; if it fails display an error and exit. +read_rom() { + /bin/flash.sh -r "$1" + if [ ! -s "$1" ]; then + whiptail $BG_COLOR_ERROR --title 'ERROR: BIOS Read Failed!' \ + --msgbox "Unable to read BIOS" 0 80 + exit 1 fi - dynamic_config_options+=( - 'x' ' Return to Main Menu' - ) - +} + +while true; do if [ ! -z "$param" ]; then # use first char from parameter menu_choice=${param::1} unset param else + # Re-source config because we change it when an option is toggled + . /tmp/config + + dynamic_config_options=( + 'b' ' Change the /boot device' + ) + + # Options that don't apply to basic mode + [ "$CONFIG_BASIC" != "y" ] && dynamic_config_options+=( + 'r' ' Clear GPG key(s) and reset all user settings' + 'R' ' Change the root device for hashing' + 'D' ' Change the root directories to hash' + 'B' ' Check root hashes at boot' + 'L' " $(get_config_display_action "$CONFIG_RESTRICTED_BOOT") Restricted Boot" + ) + + # Basic itself is always available (though RB will refuse to enable it) + dynamic_config_options+=( + 'P' " $(get_config_display_action "$CONFIG_BASIC") $CONFIG_BRAND_NAME Basic Mode" + ) + + # Blob jail is only offered if this is a configuration with the blobs in + # firmware + [ "$CONFIG_SUPPORT_BLOB_JAIL" = "y" ] && dynamic_config_options+=( + 'J' " $(get_config_display_action "$CONFIG_USE_BLOB_JAIL") Firmware Blob Jail" + ) + + # Basic-only options for automatic boot + [ "$CONFIG_BASIC" = "y" ] && dynamic_config_options+=( + 'A' " $(get_inverted_config_display_action "$CONFIG_BASIC_NO_AUTOMATIC_DEFAULT") automatic default boot" + 'U' " $(get_config_display_action "$CONFIG_BASIC_USB_AUTOBOOT") USB automatic boot" + ) + + # Automatic power on - requires board support + [ "$CONFIG_SUPPORT_AUTOMATIC_POWERON" = "y" ] && dynamic_config_options+=( + 'N' " $(get_config_display_action "$CONFIG_AUTOMATIC_POWERON") automatic power-on" + ) + + [ "$CONFIG_FINALIZE_PLATFORM_LOCKING_PRESKYLAKE" = "y" ] && dynamic_config_options+=( + 't' ' Deactivate Platform Locking to permit OS write access to firmware' + ) + + dynamic_config_options+=( + 's' ' Save the current configuration to the running BIOS' \ + 'x' ' Return to Main Menu' + ) + unset menu_choice whiptail $BG_COLOR_MAIN_MENU --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." 0 80 10 \ @@ -49,10 +94,10 @@ while true; do exit 0 ;; "b" ) - CURRENT_OPTION=`grep 'CONFIG_BOOT_DEV=' /tmp/config | tail -n1 | cut -f2 -d '=' | tr -d '"'` + CURRENT_OPTION="$(load_config_value CONFIG_BOOT_DEV)" if ! fdisk -l | grep "Disk /dev/" | cut -f2 -d " " | cut -f1 -d ":" > /tmp/disklist.txt ; then whiptail $BG_COLOR_ERROR --title 'ERROR: No bootable devices found' \ - --msgbox " $ERROR\n\n" 16 60 + --msgbox " $ERROR\n\n" 0 80 exit 1 fi # filter out extraneous options @@ -67,7 +112,7 @@ while true; do fi done file_selector "/tmp/boot_device_list.txt" \ - "Choose the default /boot device.\n\nCurrently set to $CURRENT_OPTION." \ + "Choose the default /boot device.\n\n${CURRENT_OPTION:+\n\nCurrently set to }$CURRENT_OPTION." \ "Boot Device Selection" if [ "$FILE" == "" ]; then return @@ -83,34 +128,26 @@ while true; do if ! mount -o ro $SELECTED_FILE /boot 2>/tmp/error ; then ERROR=`cat /tmp/error` whiptail $BG_COLOR_ERROR --title 'ERROR: unable to mount /boot' \ - --msgbox " $ERROR\n\n" 16 60 + --msgbox " $ERROR\n\n" 0 80 exit 1 fi - replace_config /etc/config.user "CONFIG_BOOT_DEV" "$SELECTED_FILE" + set_config /etc/config.user "CONFIG_BOOT_DEV" "$SELECTED_FILE" combine_configs whiptail --title 'Config change successful' \ - --msgbox "The /boot device was successfully changed to $SELECTED_FILE" 16 60 + --msgbox "The /boot device was successfully changed to $SELECTED_FILE" 0 80 ;; "s" ) - /bin/flash.sh -r /tmp/config-gui.rom - if [ ! -s /tmp/config-gui.rom ]; then - whiptail $BG_COLOR_ERROR --title 'ERROR: BIOS Read Failed!' \ - --msgbox "Unable to read BIOS" 16 60 - exit 1 - fi + read_rom /tmp/config-gui.rom - if (cbfs.sh -o /tmp/config-gui.rom -l | grep -q "heads/initrd/etc/config.user") then - cbfs.sh -o /tmp/config-gui.rom -d "heads/initrd/etc/config.user" - fi - cbfs.sh -o /tmp/config-gui.rom -a "heads/initrd/etc/config.user" -f /etc/config.user + replace_rom_file /tmp/config-gui.rom "heads/initrd/etc/config.user" /etc/config.user if (whiptail --title 'Update ROM?' \ --yesno "This will reflash your BIOS with the updated version\n\nDo you want to proceed?" 0 80) 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 + --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" 0 80 /bin/reboot else exit 0 @@ -123,13 +160,7 @@ while true; do \nreset the /boot device, clear/reset the TPM (if present), \nand reflash your BIOS with the cleaned configuration. \n\nDo you want to proceed?" 0 80) then - # read current firmware - /bin/flash.sh -r /tmp/config-gui.rom - if [ ! -s /tmp/config-gui.rom ]; then - whiptail $BG_COLOR_ERROR --title 'ERROR: BIOS Read Failed!' \ - --msgbox "Unable to read BIOS" 16 60 - exit 1 - fi + read_rom /tmp/config-gui.rom # clear local keyring rm /.gnupg/* | true # clear /boot signatures/checksums @@ -141,18 +172,307 @@ while true; do cbfs.sh -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 + --msgbox "Configuration reset and BIOS updated successfully.\n\nPress Enter to reboot" 0 80 /bin/reboot else exit 0 fi ;; + "R" ) + CURRENT_OPTION="$(load_config_value CONFIG_ROOT_DEV)" + fdisk -l | grep "Disk /dev/" | cut -f2 -d " " | cut -f1 -d ":" > /tmp/disklist.txt + # filter out extraneous options + > /tmp/root_device_list.txt + for i in `cat /tmp/disklist.txt`; do + # remove block device from list if numeric partitions exist, since not bootable + DEV_NUM_PARTITIONS=$((`ls -1 $i* | wc -l`-1)) + if [ ${DEV_NUM_PARTITIONS} -eq 0 ]; then + echo $i >> /tmp/root_device_list.txt + else + ls $i* | tail -${DEV_NUM_PARTITIONS} >> /tmp/root_device_list.txt + fi + done + file_selector "/tmp/root_device_list.txt" \ + "Choose the default root device.${CURRENT_OPTION:+\n\nCurrently set to }$CURRENT_OPTION." \ + "Root Device Selection" + if [ "$FILE" == "" ]; then + break + else + SELECTED_FILE=$FILE + fi + + set_config /etc/config.user "CONFIG_ROOT_DEV" "$SELECTED_FILE" + combine_configs + + whiptail --title 'Config change successful' \ + --msgbox "The root device was successfully changed to $SELECTED_FILE" 0 80 + ;; + "D" ) + CURRENT_OPTION="$(load_config_value CONFIG_ROOT_DIRLIST)" + + # Separate from prior prompt history on the terminal with two blanks + echo -e "\n" + + if [ -n "$CURRENT_OPTION" ]; then + echo -e "The current list of directories to hash is $CURRENT_OPTION" + fi + echo -e "Enter the new list of directories separated by spaces:" + echo -e "(Press enter with the list empty to cancel)" + read -r NEW_CONFIG_ROOT_DIRLIST + + # strip any leading forward slashes + NEW_CONFIG_ROOT_DIRLIST=$(echo $NEW_CONFIG_ROOT_DIRLIST | sed -e 's/^\///;s/ \// /g') + + #check if list empty + if [ -z "$NEW_CONFIG_ROOT_DIRLIST" ] ; then + whiptail --title 'Config change canceled' \ + --msgbox "Root device directory change canceled by user" 0 80 + break + fi + + set_config /etc/config.user "CONFIG_ROOT_DIRLIST" "$NEW_CONFIG_ROOT_DIRLIST" + combine_configs + + whiptail --title 'Config change successful' \ + --msgbox "The root directories to hash was successfully changed to:\n$NEW_CONFIG_ROOT_DIRLIST" 0 80 + ;; + "B" ) + CURRENT_OPTION="$(load_config_value CONFIG_ROOT_CHECK_AT_BOOT)" + if [ "$CURRENT_OPTION" != "y" ]; then + # Root device and directories must be set to enable this + if [ -z "$(load_config_value CONFIG_ROOT_DEV)" ] || [ -z "$(load_config_value CONFIG_ROOT_DIRLIST)" ]; then + whiptail $BG_COLOR_ERROR --title 'Root Check Not Configured' \ + --msgbox "Set the root device and directories to hash before enabling this feature." 0 80 + elif (whiptail --title 'Enable Root Hash Check at Boot?' \ + --yesno "This will enable checking root hashes each time you boot. + \nDepending on the directories you are checking, this might add + \na minute or more to the boot time. + \n\nDo you want to proceed?" 0 80) then + + set_config /etc/config.user "CONFIG_ROOT_CHECK_AT_BOOT" "y" + combine_configs + + # check that root hash file exists + if [ ! -f ${ROOT_HASH_FILE} ]; then + if (whiptail --title 'Generate Root Hash File' \ + --yesno "\nNo root hash file exists. + \nWould you like to create the initial hash file now?" 0 80) then + root-hashes-gui.sh -n + fi + fi + + whiptail --title 'Config change successful' \ + --msgbox "The root device will be checked at each boot." 0 80 + + fi + else + if (whiptail --title 'Disable Root Hash Check at Boot?' \ + --yesno "This will disable checking root hashes each time you boot. + \n\nDo you want to proceed?" 0 80) then + + set_config /etc/config.user "CONFIG_ROOT_CHECK_AT_BOOT" "n" + combine_configs + + whiptail --title 'Config change successful' \ + --msgbox "The root device will not be checked at each boot." 0 80 + fi + fi + ;; + "P" ) + if [ "$CONFIG_RESTRICTED_BOOT" = "y" ]; then + whiptail $BG_COLOR_ERROR --title 'Restricted Boot Active' \ + --msgbox "Disable Restricted Boot to enable Basic Mode." 0 80 + elif [ "$CONFIG_BASIC" != "y" ]; then + if (whiptail --title "Enable $CONFIG_BRAND_NAME Basic Mode?" \ + --yesno "This will remove all signature checking on the firmware + \nand boot files, and disable use of the Librem Key. + \n\nDo you want to proceed?" 0 80) then + + set_user_config "CONFIG_BASIC" "y" + + whiptail --title 'Config change successful' \ + --msgbox "$CONFIG_BRAND_NAME Basic mode enabled;\nsave the config change and reboot for it to go into effect." 0 80 + + fi + else + if (whiptail --title "Disable $CONFIG_BRAND_NAME Basic Mode?" \ + --yesno "This will enable all signature checking on the firmware + \nand boot files, and enable use of the Librem Key. + \n\nDo you want to proceed?" 0 80) then + + set_user_config "CONFIG_BASIC" "n" + + whiptail --title 'Config change successful' \ + --msgbox "$CONFIG_BRAND_NAME Basic mode has been disabled;\nsave the config change and reboot for it to go into effect." 0 80 + fi + fi + ;; + "L" ) + if [ "$CONFIG_RESTRICTED_BOOT" != "y" ]; then + if (whiptail --title 'Enable Restricted Boot Mode?' \ + --yesno "Restricted Boot allows booting: + \n* Signed installed OS + \n* Signed ISOs from USB + \nAll other boot methods are blocked. Recovery console and firmware updates + \nwill be blocked. + \nRestricted boot can be disabled at any time. This resets TOTP/HOTP so it + \nis evident that Restricted Boot was disabled. + \n + \nDo you want to proceed?" 0 80) then + + set_user_config "CONFIG_RESTRICTED_BOOT" "y" + + whiptail --title 'Config change successful' \ + --msgbox "Restricted Boot mode enabled;\nsave the config change and reboot for it to go into effect." 0 80 + + fi + else + if (whiptail --title 'Disable Restricted Boot Mode?' \ + --yesno "This will re-enable all boot methods, the recovery console, and firmware + \nupdates. + \nThis will also erase the TOTP/HOTP secret. + \nProceeding will automatically update the boot firmware and reboot! + \n\nDo you want to proceed?" 0 80) then + + # Wipe the TPM TOTP/HOTP secret before flashing. Otherwise, enabling + # Restricted Boot again might restore the firmware to an identical + # state, and there would be no evidence that it had been temporarily + # disabled. + if ! wipe-totp >/dev/null 2>/tmp/error; then + ERROR=$(tail -n 1 /tmp/error | fold -s) + whiptail $BG_COLOR_ERROR --title 'ERROR: erasing TOTP secret' \ + --msgbox "Erasing TOTP Secret Failed\n\n${ERROR}" 0 80 + exit 1 + fi + + # We can't allow Restricted Boot to be disabled without flashing the + # firmware - this would allow the use of unrestricted mode without + # leaving evidence in the firmware. Disable it by flashing the new + # config directly. + FLASH_USER_CONFIG=/tmp/config-gui-config-user + cp /etc/config.user "$FLASH_USER_CONFIG" + set_config "$FLASH_USER_CONFIG" "CONFIG_RESTRICTED_BOOT" "n" + + read_rom /tmp/config-gui.rom + + replace_rom_file /tmp/config-gui.rom "heads/initrd/etc/config.user" "$FLASH_USER_CONFIG" + + /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" 0 80 + /bin/reboot + fi + fi + ;; + "J" ) + if [ "$CONFIG_USE_BLOB_JAIL" != "y" ]; then + if (whiptail --title 'Enable Firmware Blob Jail?' \ + --yesno "This will enable loading of firmware from flash on each boot + \n\nDo you want to proceed?" 0 80) then + + set_user_config "CONFIG_USE_BLOB_JAIL" "y" + + whiptail --title 'Config change successful' \ + --msgbox "Firmware Blob Jail use has been enabled;\nsave the config change and reboot for it to go into effect." 0 80 + + fi + else + if (whiptail --title 'Disable Firmware Blob Jail?' \ + --yesno "This will disable loading of firmware from flash on each boot. + \n\nDo you want to proceed?" 0 80) then + + set_user_config "CONFIG_USE_BLOB_JAIL" "n" + + whiptail --title 'Config change successful' \ + --msgbox "Firmware Blob Jail use has been disabled;\nsave the config change and reboot for it to go into effect." 0 80 + fi + fi + ;; + "A" ) + if [ "$CONFIG_BASIC_NO_AUTOMATIC_DEFAULT" != "y" ]; then + if (whiptail --title 'Disable automatic default boot?' \ + --yesno "You will need to select a default boot option. + \nIf the boot options are changed, such as for an OS update, + \nyou will be prompted to select a new default. + \n\nDo you want to proceed?" 0 80) then + + set_user_config "CONFIG_BASIC_NO_AUTOMATIC_DEFAULT" "y" + + whiptail --title 'Config change successful' \ + --msgbox "Automatic default boot disabled;\nsave the config change and reboot for it to go into effect." 0 80 + fi + else + if (whiptail --title 'Enable automatic default boot?' \ + --yesno "The first boot option will be used automatically. + \n\nDo you want to proceed?" 0 80) then + + set_user_config "CONFIG_BASIC_NO_AUTOMATIC_DEFAULT" "n" + + whiptail --title 'Config change successful' \ + --msgbox "Automatic default boot enabled;\nsave the config change and reboot for it to go into effect." 0 80 + fi + fi + ;; + "U" ) + if [ "$CONFIG_BASIC_USB_AUTOBOOT" != "y" ]; then + if (whiptail --title 'Enable USB automatic boot?' \ + --yesno "During boot, an attached bootable USB disk will be booted + \nby default instead of the installed operating system. + \n\nDo you want to proceed?" 0 80) then + + set_user_config "CONFIG_BASIC_USB_AUTOBOOT" "y" + + whiptail --title 'Config change successful' \ + --msgbox "USB automatic boot enabled;\nsave the config change and reboot for it to go into effect." 0 80 + fi + else + if (whiptail --title 'Disable USB automatic boot?' \ + --yesno "USB disks will no longer be booted by default. + \n\nDo you want to proceed?" 0 80) then + + set_user_config "CONFIG_BASIC_USB_AUTOBOOT" "n" + + whiptail --title 'Config change successful' \ + --msgbox "USB automatic boot disabled;\nsave the config change and reboot for it to go into effect." 0 80 + fi + fi + ;; + "N" ) + if [ "$CONFIG_AUTOMATIC_POWERON" != "y" ]; then + if (whiptail --title 'Enable automatic power-on?' \ + --yesno "The system will boot automatically when power is applied. + \n\nDo you want to proceed?" 0 80) then + + set_user_config "CONFIG_AUTOMATIC_POWERON" "y" + + whiptail --title 'Config change successful' \ + --msgbox "Automatic power-on enabled;\nsave the config change and reboot for it to go into effect." 0 80 + fi + else + if (whiptail --title 'Disable automatic power-on?' \ + --yesno "The system will stay off when power is applied. + \n\nDo you want to proceed?" 0 80) then + + set_user_config "CONFIG_AUTOMATIC_POWERON" "n" + + # Disable the EC BRAM setting too, otherwise it persists until + # manually disabled. On the off chance the user does not actually + # flash this change, we'll enable it again during boot. + set_ec_poweron.sh n + + whiptail --title 'Config change successful' \ + --msgbox "Automatic power-on disabled;\nsave the config change and reboot for it to go into effect." 0 80 + fi + fi + ;; esac done diff --git a/initrd/bin/flash-gui.sh b/initrd/bin/flash-gui.sh index e952272f5..f52373909 100755 --- a/initrd/bin/flash-gui.sh +++ b/initrd/bin/flash-gui.sh @@ -7,6 +7,12 @@ set -e -o pipefail TRACE "Under /bin/flash-gui.sh" +if [ "$CONFIG_RESTRICTED_BOOT" = y ]; then + whiptail $BG_COLOR_ERROR --title 'Restricted Boot Active' \ + --msgbox "Disable Restricted Boot to flash new firmware." 0 80 + exit 1 +fi + while true; do unset menu_choice whiptail $BG_COLOR_MAIN_MENU --title "Firmware Management Menu" \ diff --git a/initrd/bin/gpg-gui.sh b/initrd/bin/gpg-gui.sh index e0c484cad..f2406e53a 100755 --- a/initrd/bin/gpg-gui.sh +++ b/initrd/bin/gpg-gui.sh @@ -73,7 +73,7 @@ gpg_flash_rom() { fi whiptail --title 'Files in /boot Updated Successfully'\ - --msgbox "Checksums have been updated and /boot files signed.\n\nPress Enter to reboot" 16 60 + --msgbox "Checksums have been updated and /boot files signed.\n\nPress Enter to reboot" 0 80 /bin/reboot } @@ -99,7 +99,7 @@ gpg_post_gen_mgmt() { /bin/flash.sh -r /tmp/gpg-gui.rom if [ ! -s /tmp/gpg-gui.rom ]; then whiptail $BG_COLOR_ERROR --title 'ERROR: BIOS Read Failed!' \ - --msgbox "Unable to read BIOS" 16 60 + --msgbox "Unable to read BIOS" 0 80 exit 1 fi PUBKEY="/tmp/${GPG_GEN_KEY}.asc" @@ -125,7 +125,7 @@ gpg_add_key_reflash() { /bin/flash.sh -r /tmp/gpg-gui.rom if [ ! -s /tmp/gpg-gui.rom ]; then whiptail $BG_COLOR_ERROR --title 'ERROR: BIOS Read Failed!' \ - --msgbox "Unable to read BIOS" 16 60 + --msgbox "Unable to read BIOS" 0 80 exit 1 fi @@ -216,10 +216,10 @@ while true; do cp "/tmp/public-key.asc" "/media/public-key.asc" if [ $? -eq 0 ]; then whiptail --title "The GPG Key Copied Successfully" \ - --msgbox "public-key.asc copied successfully." 16 60 + --msgbox "public-key.asc copied successfully." 0 80 else whiptail $BG_COLOR_ERROR --title 'ERROR: Copy Failed' \ - --msgbox "Unable to copy public-key.asc to /media" 16 60 + --msgbox "Unable to copy public-key.asc to /media" 0 80 fi umount /media fi diff --git a/initrd/bin/gui-init b/initrd/bin/gui-init index c4063dca7..58ff4a7b3 100755 --- a/initrd/bin/gui-init +++ b/initrd/bin/gui-init @@ -2,10 +2,11 @@ # Boot from a local disk installation BOARD_NAME=${CONFIG_BOARD_NAME:-${CONFIG_BOARD}} -MAIN_MENU_TITLE="${BOARD_NAME} | Heads Boot Menu" +MAIN_MENU_TITLE="${BOARD_NAME} | $CONFIG_BRAND_NAME Boot Menu" export BG_COLOR_MAIN_MENU="" . /etc/functions +. /etc/gui_functions . /etc/luks-functions . /tmp/config @@ -93,7 +94,7 @@ verify_global_hashes() # if files changed before package manager started, show stern warning if [ -f "$TMP_PACKAGE_TRIGGER_PRE" ]; then PRE_CHANGED_FILES=$(grep '^CHANGED_FILES' $TMP_PACKAGE_TRIGGER_POST | cut -f 2 -d '=' | tr -d '"') - TEXT="The following files failed the verification process BEFORE package updates ran:\n${PRE_CHANGED_FILES}\n\nCompare against the files Heads has detected have changed:\n${CHANGED_FILES}\n\nThis could indicate a compromise!\n\nWould you like to update your checksums anyway?" + TEXT="The following files failed the verification process BEFORE package updates ran:\n${PRE_CHANGED_FILES}\n\nCompare against the files $CONFIG_BRAND_NAME has detected have changed:\n${CHANGED_FILES}\n\nThis could indicate a compromise!\n\nWould you like to update your checksums anyway?" # if files changed after package manager started, probably caused by package manager elif [ -f "$TMP_PACKAGE_TRIGGER_POST" ]; then @@ -110,7 +111,7 @@ verify_global_hashes() if [ $CHANGED_FILES_COUNT -gt 10 ]; then # drop to console to show full file list whiptail $ERROR_BG_COLOR --title 'ERROR: Boot Hash Mismatch' \ - --msgbox "${CHANGED_FILES_COUNT} files failed the verification process!\\n\nThis could indicate a compromise!\n\nHit OK to review the list of files.\n\nType \"q\" to exit the list and return." 16 60 + --msgbox "${CHANGED_FILES_COUNT} files failed the verification process!\\n\nThis could indicate a compromise!\n\nHit OK to review the list of files.\n\nType \"q\" to exit the list and return." 0 80 echo "Type \"q\" to exit the list and return." >> /tmp/hash_output_mismatches less /tmp/hash_output_mismatches @@ -152,15 +153,22 @@ generate_totp_hotp() { tpm_password="$1" # May be empty, will prompt if needed and empty TRACE "Under /bin/gui-init:generate_totp_hotp" - echo "Scan the QR code to add the new TOTP secret" - if /bin/seal-totp "$BOARD_NAME" "$tpm_password"; then + if [ "$CONFIG_TPM" != "y" ] && [ -x /bin/hotp_verification ]; then + echo "Generating new HOTP secret" + /bin/seal-hotpkey + elif echo -e "Generating new TOTP secret...\n\n" && /bin/seal-totp "$BOARD_NAME" "$tpm_password"; then + echo if [ -x /bin/hotp_verification ]; then - echo "Once you have scanned the QR code, hit Enter to configure your HOTP USB Security Dongle (e.g. Librem Key or Nitrokey)" - read + if [ "$CONFIG_TOTP_SKIP_QRCODE" != y ]; then + echo "Once you have scanned the QR code, hit Enter to configure your HOTP USB Security Dongle (e.g. Librem Key or Nitrokey)" + read + fi /bin/seal-hotpkey else - echo "Once you have scanned the QR code, hit Enter to continue" - read + if [ "$CONFIG_TOTP_SKIP_QRCODE" != y ]; then + echo "Once you have scanned the QR code, hit Enter to continue" + read + fi fi # clear screen printf "\033c" @@ -202,7 +210,7 @@ update_totp() DEBUG "$(pcrs)" whiptail $BG_COLOR_ERROR --title "ERROR: TOTP Generation Failed!" \ - --menu " ERROR: Heads couldn't generate the TOTP code.\n + --menu " ERROR: $CONFIG_BRAND_NAME couldn't generate the TOTP code.\n If you have just completed a Factory Reset, or just reflashed your BIOS, you should generate a new HOTP/TOTP secret.\n If this is the first time the system has booted, you should @@ -275,6 +283,31 @@ update_hotp() else HOTP='N/A' fi + + if [[ "$CONFIG_TPM" = n && "$HOTP" = "Invalid code" ]]; then + whiptail $BG_COLOR_ERROR --title "ERROR: HOTP Validation Failed!" \ + --menu "ERROR: $CONFIG_BRAND_NAME couldn't validate the HOTP code.\n\nIf you just reflashed your BIOS, you should generate a new TOTP/HOTP secret.\n\nIf you have not just reflashed your BIOS, THIS COULD INDICATE TAMPERING!\n\nHow would you like to proceed?" 0 80 4 \ + 'g' ' Generate new TOTP/HOTP secret' \ + 'i' ' Ignore error and continue to main menu' \ + 'x' ' Exit to recovery shell' \ + 2>/tmp/whiptail || recovery "GUI menu failed" + + option=$(cat /tmp/whiptail) + case "$option" in + g ) + if (whiptail $BG_COLOR_WARNING --title 'Generate new TOTP/HOTP secret' \ + --yesno "This will erase your old secret and replace it with a new one!\n\nDo you want to proceed?" 0 80) then + generate_totp_hotp && BG_COLOR_MAIN_MENU="" + fi + ;; + i ) + return 1 + ;; + x ) + recovery "User requested recovery shell" + ;; + esac + fi } clean_boot_check() @@ -316,7 +349,7 @@ check_gpg_key() return 1 # Already asked to skip to menu from a prior error fi whiptail $BG_COLOR_ERROR --title "ERROR: GPG keyring empty!" \ - --menu "ERROR: Heads couldn't find any GPG keys in your keyring.\n\nIf this is the first time the system has booted,\nyou should add a public GPG key to the BIOS now.\n\nIf you just reflashed a new BIOS, you'll need to add at least one\npublic key to the keyring.\n\nIf you have not just reflashed your BIOS, THIS COULD INDICATE TAMPERING!\n\nHow would you like to proceed?" 0 80 4 \ + --menu "ERROR: $CONFIG_BRAND_NAME couldn't find any GPG keys in your keyring.\n\nIf this is the first time the system has booted,\nyou should add a public GPG key to the BIOS now.\n\nIf you just reflashed a new BIOS, you'll need to add at least one\npublic key to the keyring.\n\nIf you have not just reflashed your BIOS, THIS COULD INDICATE TAMPERING!\n\nHow would you like to proceed?" 0 80 4 \ 'g' ' Add a GPG key to the running BIOS' \ 'F' ' OEM Factory Reset / Re-Ownership' \ 'i' ' Ignore error and continue to main menu' \ @@ -346,18 +379,11 @@ check_gpg_key() prompt_auto_default_boot() { TRACE "Under /bin/gui-init:prompt_auto_default_boot" - # save IFS before changing, restore after read - IFS_DEF=$IFS - IFS='' - first_pass=false echo -e "\nHOTP verification success\n\n" - read -t $CONFIG_AUTO_BOOT_TIMEOUT -s -n 1 -p "Automatic boot in $CONFIG_AUTO_BOOT_TIMEOUT seconds unless interrupted by keypress... " - if [[ $? -ne 0 ]]; then - IFS=$IFS_DEF + if pause_automatic_boot; then echo -e "\n\nAttempting default boot...\n\n" attempt_default_boot fi - IFS=$IFS_DEF } show_main_menu() @@ -396,7 +422,7 @@ show_main_menu() show_options_menu() { TRACE "Under /bin/gui-init:show_options_menu" - whiptail $BG_COLOR_MAIN_MENU --title "HEADS Options" \ + whiptail $BG_COLOR_MAIN_MENU --title "$CONFIG_BRAND_NAME Options" \ --menu "" 0 80 10 \ 'b' ' Boot Options -->' \ 't' ' TPM/TOTP/HOTP Options -->' \ @@ -405,8 +431,9 @@ show_options_menu() 'f' ' Flash/Update the BIOS -->' \ 'g' ' GPG Options -->' \ 'F' ' OEM Factory Reset / Re-Ownership -->' \ - 'R' ' Reencrypt LUKS container -->' \ - 'C' ' Change LUKS Disk Recovery Key passphrase ->' \ + 'C' ' Reencrypt LUKS container -->' \ + 'P' ' Change LUKS Disk Recovery Key passphrase ->' \ + 'R' ' Check/Update file hashes on root disk -->' \ 'x' ' Exit to recovery shell' \ 'r' ' <-- Return to main menu' \ 2>/tmp/whiptail || recovery "GUI menu failed" @@ -434,14 +461,17 @@ show_options_menu() F ) oem-factory-reset ;; - R ) + C ) luks_reencrypt luks_secrets_cleanup ;; - C ) + P ) luks_change_passphrase luks_secrets_cleanup ;; + R ) + root-hashes-gui.sh + ;; x ) recovery "User requested recovery shell" ;; @@ -565,24 +595,6 @@ reset_tpm() fi } -show_system_info() -{ - TRACE "Under /bin/gui-init:show_system_info" - battery_charge="$(print_battery_charge)" - battery_health="$(print_battery_health)" - if [ -n $battery_charge -a -n $battery_health ];then - battery_status="\nBattery charge: $battery_charge%\nBattery health: $battery_health%\n" - fi - - memtotal=$(cat /proc/meminfo | grep 'MemTotal' | tr -s ' ' | cut -f2 -d ' ') - memtotal=$((${memtotal} / 1024 / 1024 + 1)) - cpustr=$(cat /proc/cpuinfo | grep 'model name' | uniq | sed -r 's/\(R\)//;s/\(TM\)//;s/CPU //;s/model name.*: //') - kernel=$(uname -s -r) - - whiptail $BG_COLOR_MAIN_MENU --title 'System Info' \ - --msgbox "${BOARD_NAME}\n\nFW_VER: ${FW_VER}\nKernel: ${kernel}\n\nCPU: ${cpustr}\nRAM: ${memtotal} GB\n$battery_status\n$(fdisk -l | grep -e '/dev/sd.:' -e '/dev/nvme.*:' | sed 's/B,.*/B/')" 16 60 -} - select_os_boot_option() { TRACE "Under /bin/gui-init:select_os_boot_option" @@ -613,6 +625,10 @@ attempt_default_boot() force_unsafe_boot() { TRACE "Under /bin/gui-init:force_unsafe_boot" + if [ "$CONFIG_RESTRICTED_BOOT" = y ]; then + whiptail $BG_COLOR_ERROR --title 'ERROR: Restricted Boot Enabled' --msgbox "Restricted Boot is Enabled, forced boot not allowed.\n\nPress OK to return to the Main Menu" 0 80 + return + fi # Run the menu selection in "force" mode, bypassing hash checks if (whiptail $BG_COLOR_WARNING --title 'Unsafe Forced Boot Selected!' \ --yesno "WARNING: You have chosen to skip all tamper checks and boot anyway.\n\nThis is an unsafe option!\n\nDo you want to proceed?" 0 80) then diff --git a/initrd/bin/gui-init-basic b/initrd/bin/gui-init-basic new file mode 100755 index 000000000..95243e89c --- /dev/null +++ b/initrd/bin/gui-init-basic @@ -0,0 +1,212 @@ +#!/bin/bash +# Boot from a local disk installation + +BOARD_NAME=${CONFIG_BOARD_NAME:-${CONFIG_BOARD}} +MAIN_MENU_TITLE="${BOARD_NAME} | $CONFIG_BRAND_NAME Basic Boot Menu" +export BG_COLOR_MAIN_MENU="" + +. /etc/functions +. /etc/gui_functions +. /tmp/config + +# skip_to_menu is set if the user selects "continue to the main menu" from any +# error, so we will indeed go to the main menu even if other errors occur. It's +# reset when we reach the main menu so the user can retry from the main menu and +# # see errors again. +skip_to_menu="false" + +mount_boot() +{ + TRACE "Under /bin/gui-init:mount_boot" + # Mount local disk if it is not already mounted + while ! grep -q /boot /proc/mounts ; do + # try to mount if CONFIG_BOOT_DEV exists + if [ -e "$CONFIG_BOOT_DEV" ]; then + mount -o ro $CONFIG_BOOT_DEV /boot + [[ $? -eq 0 ]] && continue + fi + + # CONFIG_BOOT_DEV doesn't exist or couldn't be mounted, so give user options + BG_COLOR_MAIN_MENU=$BG_COLOR_ERROR + whiptail $BG_COLOR_ERROR --title "ERROR: No Bootable OS Found!" \ + --menu " No bootable OS was found on the default boot device $CONFIG_BOOT_DEV. + How would you like to proceed?" 0 80 4 \ + 'b' ' Select a new boot device' \ + 'u' ' Boot from USB' \ + 'm' ' Continue to the main menu' \ + 'x' ' Exit to recovery shell' \ + 2>/tmp/whiptail || recovery "GUI menu failed" + + option=$(cat /tmp/whiptail) + case "$option" in + b ) + config-gui.sh boot_device_select + if [ $? -eq 0 ]; then + # update CONFIG_BOOT_DEV + . /tmp/config + BG_COLOR_MAIN_MENU="" + fi + ;; + u ) + exec /bin/usb-init + ;; + m ) + skip_to_menu="true" + break + ;; + * ) + recovery "User requested recovery shell" + ;; + esac + done +} + +prompt_auto_default_boot() +{ + TRACE "Under /bin/gui-init:prompt_auto_default_boot" + echo -e "\n\n" + if pause_automatic_boot; then + echo -e "\n\nAttempting default boot...\n\n" + attempt_default_boot + fi +} + +show_main_menu() +{ + TRACE "Under /bin/gui-init:show_main_menu" + date=`date "+%Y-%m-%d %H:%M:%S %Z"` + whiptail $BG_COLOR_MAIN_MENU --title "$MAIN_MENU_TITLE" \ + --menu "$date" 0 80 10 \ + 'd' ' Default boot' \ + 'o' ' Options -->' \ + 's' ' System Info' \ + 'p' ' Power Off' \ + 2>/tmp/whiptail || recovery "GUI menu failed" + + option=$(cat /tmp/whiptail) + case "$option" in + d ) + attempt_default_boot + ;; + o ) + show_options_menu + ;; + s ) + show_system_info + ;; + p ) + poweroff + ;; + esac +} + +show_options_menu() +{ + TRACE "Under /bin/gui-init:show_options_menu" + whiptail $BG_COLOR_MAIN_MENU --title "$CONFIG_BRAND_NAME Basic Options" \ + --menu "" 0 80 10 \ + 'b' ' Boot Options -->' \ + 'c' ' Change configuration settings -->' \ + 'f' ' Flash/Update the BIOS -->' \ + 'x' ' Exit to recovery shell' \ + 'r' ' <-- Return to main menu' \ + 2>/tmp/whiptail || recovery "GUI menu failed" + + option=$(cat /tmp/whiptail) + case "$option" in + b ) + show_boot_options_menu + ;; + c ) + config-gui.sh + ;; + f ) + flash-gui.sh + ;; + x ) + recovery "User requested recovery shell" + ;; + r ) + ;; + esac +} + +show_boot_options_menu() +{ + TRACE "Under /bin/gui-init:show_boot_options_menu" + whiptail $BG_COLOR_MAIN_MENU --title "Boot Options" \ + --menu "Select A Boot Option" 0 80 10 \ + 'm' ' Show OS boot menu' \ + 'u' ' USB boot' \ + 'r' ' <-- Return to main menu' \ + 2>/tmp/whiptail || recovery "GUI menu failed" + + option=$(cat /tmp/whiptail) + case "$option" in + m ) + # select a kernel from the menu + select_os_boot_option + ;; + u ) + exec /bin/usb-init + ;; + r ) + ;; + esac +} + +select_os_boot_option() +{ + TRACE "Under /bin/gui-init:select_os_boot_option" + mount_boot + kexec-select-boot -m -b /boot -c "grub.cfg" -g -i +} + +attempt_default_boot() +{ + TRACE "Under /bin/gui-init:attempt_default_boot" + mount_boot + + DEFAULT_FILE=`find /boot/kexec_default.*.txt 2>/dev/null | head -1` + # Basic by default boots automatically to the first menu option. This allows + # kernel updates to work in Basic by default without prompting to select a + # new default boot option. + if [ "$CONFIG_BASIC_NO_AUTOMATIC_DEFAULT" != "y" ]; then + basic-autoboot.sh + elif [ -r "$DEFAULT_FILE" ]; then + kexec-select-boot -b /boot -c "grub.cfg" -g -i -s \ + || recovery "Failed default boot" + elif (whiptail $BG_COLOR_WARNING --title 'No Default Boot Option Configured' \ + --yesno "There is no default boot option configured yet.\nWould you like to load a menu of boot options?\nOtherwise you will return to the main menu." 0 80) then + kexec-select-boot -m -b /boot -c "grub.cfg" -g -i + fi +} + +# gui-init-basic start +TRACE "Under /bin/gui-init, start" + +# USB automatic boot (if configured) occurs before mounting /boot, this should +# work even if no OS is installed +if [ "$CONFIG_BASIC_USB_AUTOBOOT" = "y" ] && usb-autoboot.sh; then + # USB autoboot was offered and interrupted. Don't offer the default boot, + # go to the menu. + skip_to_menu=true +fi + +if ! detect_boot_device ; then + # can't determine /boot device or no OS installed, + # so fall back to interactive selection + mount_boot +fi + +if [ "$skip_to_menu" != "true" -a -n "$CONFIG_AUTO_BOOT_TIMEOUT" ]; then + prompt_auto_default_boot +fi + +while true; do + TRACE "Under gui-init:while true loop" + skip_to_menu="false" + show_main_menu +done + +recovery "Something failed during boot" diff --git a/initrd/bin/inject_firmware.sh b/initrd/bin/inject_firmware.sh new file mode 100755 index 000000000..452e931fb --- /dev/null +++ b/initrd/bin/inject_firmware.sh @@ -0,0 +1,94 @@ +#!/bin/bash + +# If blob jail is enabled, copy initrd and inject firmware. +# Prints new initrd path (in memory) if firmware was injected. +# +# This does not alter the initrd on disk: +# * Signatures are not invalidated +# * If the injection fails for any reason, we just proceed with the original +# initrd (lacking firmware, but still booting). +# * If, somehow, this injection malfunctions (without failing outright) and +# prevents a boot, the user can work around it just by disabling blob jail. +# We do not risk ruining the real initrd. +# +# The injection has some requirements on the initrd that are all true for +# Debian: +# * initrd must be a gzipped cpio (Linux supports other compression methods) +# * /init must be a shell script (so we can inject a command to copy firmware) +# * There must be an 'exec run-init ... ${rootmnt} ...' line that moves the +# real root to / and invokes init +# +# If the injection can't be performed, boot will continue with no firmware. + +set -e -o pipefail + +. /tmp/config +. /etc/functions + +if [ "$(load_config_value CONFIG_USE_BLOB_JAIL)" != "y" ]; then + # Blob jail not active, nothing to do + exit 0 +fi + +ORIG_INITRD="$1" + +# Extract the init script from the initrd +INITRD_ROOT="/tmp/inject_firmware_initrd_root" +rm -rf "$INITRD_ROOT" || true +mkdir "$INITRD_ROOT" +# Unpack just 'init' from the original initrd +unpack_initramfs.sh "$ORIG_INITRD" "$INITRD_ROOT" init + +# Copy the firmware into the initrd +for f in $(cbfs -l | grep firmware); do + mkdir -p "$INITRD_ROOT/$(dirname "$f")" + cbfs -r "$f" > "$INITRD_ROOT/$f" + if [[ "$f" == *.lzma ]]; then + lzma -d "$INITRD_ROOT/$f" + fi +done + +# awk will happily pass through a binary file, so look for the match we want +# before modifying init to ensure it's a shell script and not an ELF, etc. +if ! grep -E -q '^exec run-init .*\$\{rootmnt\}' "$INITRD_ROOT/init"; then + WARN "Can't apply firmware blob jail, unknown init script" + exit 0 +fi + +# The initrd's /init has to copy the firmware to /run/firmware, so it will be +# present when the real root is moved to /. +# * Wi-Fi/BT firmware loading doesn't happen during the initrd - these modules +# aren't in the initrd anyway, typically. +# * /run is a tmpfs mount, so this works even if the root filesystem is +# read-only, and it doesn't persist anything. +# +# kexec-boot will add a kernel parameter for the kernel to look for firmware in +# /run/firmware. +# +# Debian's init script ends with an "exec run-init ..." (followed by a few lines +# to print a message in case it fails). At that point, root is mounted, and +# run-init will move it to / and then exec init. We can copy the firmware just +# before that, so we don't have to know anything about how root was mounted. +# +# The root path is in ${rootmnt}, which should appear in the run-init command. +# If it doesn't, then we don't understand the init script. +AWK_INSERT_CP=' +BEGIN{inserted=0} +/^exec run-init .*\$\{rootmnt\}/ && inserted==0 {print "cp -r /firmware ${rootmnt}/run/firmware"; inserted=1} +{print $0}' + +awk -e "$AWK_INSERT_CP" "$INITRD_ROOT/init" >"$INITRD_ROOT/init_fw" +mv "$INITRD_ROOT/init_fw" "$INITRD_ROOT/init" +chmod a+x "$INITRD_ROOT/init" + +# Pad the original initrd to 512 byte blocks. Uncompressed cpio contents must +# be 4-byte aligned, and anecdotally gzip frames might not be padded by dracut. +# Linux ignores zeros between archive segments, so any extra padding is not +# harmful. +FW_INITRD="/tmp/inject_firmware_initrd.cpio.gz" +dd if="$ORIG_INITRD" of="$FW_INITRD" bs=512 conv=sync status=none +# Pack up the new contents and append to the initrd. Don't spend time +# compressing this. +(cd "$INITRD_ROOT"; find . | cpio -o -H newc) >>"$FW_INITRD" +# Use this initrd +echo "$FW_INITRD" diff --git a/initrd/bin/kexec-boot b/initrd/bin/kexec-boot index 6fa88efde..9cfc65531 100755 --- a/initrd/bin/kexec-boot +++ b/initrd/bin/kexec-boot @@ -34,6 +34,10 @@ kexeccmd="kexec" cmdadd="$CONFIG_BOOT_KERNEL_ADD $cmdadd" cmdremove="$CONFIG_BOOT_KERNEL_REMOVE $cmdremove" +if [ "$(load_config_value CONFIG_USE_BLOB_JAIL)" = "y" ]; then + cmdadd="$cmdadd firmware_class.path=/run/firmware/" +fi + fix_file_path() { if [ "$printfiles" = "y" ]; then # output file relative to local boot directory @@ -120,6 +124,10 @@ do if [ -n "$override_initrd" ]; then filepath="$override_initrd" fi + firmware_initrd="$(inject_firmware.sh "$filepath" || true)" + if [ -n "$firmware_initrd" ]; then + filepath="$firmware_initrd" + fi kexeccmd="$kexeccmd --initrd=$filepath" fi if [ "$key" = "append" ]; then diff --git a/initrd/bin/kexec-save-default b/initrd/bin/kexec-save-default index bb76dbe3f..559813b04 100755 --- a/initrd/bin/kexec-save-default +++ b/initrd/bin/kexec-save-default @@ -48,7 +48,7 @@ fi KEY_DEVICES="$paramsdir/kexec_key_devices.txt" KEY_LVM="$paramsdir/kexec_key_lvm.txt" save_key="n" -if [ "$CONFIG_TPM" = "y" ] && [ "$CONFIG_TPM_NO_LUKS_DISK_UNLOCK" != "y" ]; then +if [ "$CONFIG_TPM" = "y" ] && [ "$CONFIG_TPM_NO_LUKS_DISK_UNLOCK" != "y" ] && [ "$CONFIG_BASIC" != y ]; then if [ ! -r "$KEY_DEVICES" ]; then read \ -n 1 \ @@ -194,8 +194,9 @@ if [ "$CONFIG_TPM" = "y" ];then extparam=-r fi fi -kexec-sign-config -p $paramsdir $extparam \ -|| die "Failed to sign default config" - +if [ "$CONFIG_BASIC" != "y" ]; then + kexec-sign-config -p $paramsdir $extparam \ + || die "Failed to sign default config" +fi # switch back to ro mode mount -o ro,remount $paramsdev diff --git a/initrd/bin/kexec-select-boot b/initrd/bin/kexec-select-boot index 219b91de6..beacc69c5 100755 --- a/initrd/bin/kexec-select-boot +++ b/initrd/bin/kexec-select-boot @@ -82,6 +82,23 @@ verify_global_hashes() fi die "$TMP_HASH_FILE: boot hash mismatch" fi + # If user enables it, check root hashes before boot as well + if [[ "$CONFIG_ROOT_CHECK_AT_BOOT" = "y" && "$force_menu" == "n" ]]; then + if root-hashes-gui.sh -c; then + echo "+++ Verified root hashes, continuing boot " + # if user re-signs, it wipes out saved options, so scan the boot directory and generate + if [ ! -r "$TMP_MENU_FILE" ]; then + scan_options + fi + else + # root-hashes-gui.sh handles the GUI error menu, just die here + if [ "$gui_menu" = "y" ]; then + whiptail $BG_COLOR_ERROR --title 'ERROR: Root Hash Mismatch' \ + --msgbox "The root hash check failed!\nExiting to a recovery shell" 0 80 + fi + die "root hash mismatch, see /tmp/hash_output_mismatches for details" + fi + fi } verify_rollback_counter() @@ -180,18 +197,7 @@ parse_option() { scan_options() { echo "+++ Scanning for unsigned boot options" option_file="/tmp/kexec_options.txt" - if [ -r $option_file ]; then rm $option_file; fi - for i in `find $bootdir -name "$config"`; do - DO_WITH_DEBUG kexec-parse-boot "$bootdir" "$i" >> $option_file - done - # FC29/30+ may use BLS format grub config files - # https://fedoraproject.org/wiki/Changes/BootLoaderSpecByDefault - # only parse these if $option_file is still empty - if [ ! -s $option_file ] && [ -d "$bootdir/loader/entries" ]; then - for i in `find $bootdir -name "$config"`; do - kexec-parse-bls "$bootdir" "$i" "$bootdir/loader/entries" >> $option_file - done - fi + scan_boot_options "$bootdir" "$config" "$option_file" if [ ! -s $option_file ]; then die "Failed to parse any boot options" fi @@ -244,26 +250,27 @@ default_select() { if [ "$option" != "$expectedoption" ]; then if [ "$gui_menu" = "y" ]; then whiptail $BG_COLOR_ERROR --title 'ERROR: Boot Entry Has Changed' \ - --msgbox "The list of boot entries has changed\n\nPlease set a new default" 16 60 + --msgbox "The list of boot entries has changed\n\nPlease set a new default" 0 80 fi warn "!!! Boot entry has changed - please set a new default" return fi parse_option - # Enforce that default option hashes are valid - echo "+++ Checking verified default boot hash file " - # Check the hashes of all the files - if ( cd $bootdir && sha256sum -c "$TMP_DEFAULT_HASH_FILE" > /tmp/hash_output ); then - echo "+++ Verified default boot hashes " - valid_hash='y' - else - if [ "$gui_menu" = "y" ]; then - CHANGED_FILES=$(grep -v 'OK$' /tmp/hash_output | cut -f1 -d ':') - whiptail $BG_COLOR_ERROR --title 'ERROR: Default Boot Hash Mismatch' \ - --msgbox "The following files failed the verification process:\n${CHANGED_FILES}\nExiting to a recovery shell" 0 80 + if [ "$CONFIG_BASIC" != "y" ]; then + # Enforce that default option hashes are valid + echo "+++ Checking verified default boot hash file " + # Check the hashes of all the files + if ( cd $bootdir && sha256sum -c "$TMP_DEFAULT_HASH_FILE" > /tmp/hash_output ); then + echo "+++ Verified default boot hashes " + valid_hash='y' + else + if [ "$gui_menu" = "y" ]; then + CHANGED_FILES=$(grep -v 'OK$' /tmp/hash_output | cut -f1 -d ':') + whiptail $BG_COLOR_ERROR --title 'ERROR: Default Boot Hash Mismatch' \ + --msgbox "The following files failed the verification process:\n${CHANGED_FILES}\nExiting to a recovery shell" 0 80 + fi fi - die "!!! $TMP_DEFAULT_HASH_FILE: default boot hash mismatch" fi echo "+++ Executing default boot for $name:" @@ -314,15 +321,15 @@ user_select() { do_boot() { - if [ "$CONFIG_BOOT_REQ_ROLLBACK" = "y" -a "$valid_rollback" = "n" ]; then + if [ "$CONFIG_BASIC" != y ] && [ "$CONFIG_BOOT_REQ_ROLLBACK" = "y" ] && [ "$valid_rollback" = "n" ]; then die "!!! Missing required rollback counter state" fi - if [ "$CONFIG_BOOT_REQ_HASH" = "y" -a "$valid_hash" = "n" ]; then + if [ "$CONFIG_BASIC" != y ] && [ "$CONFIG_BOOT_REQ_HASH" = "y" ] && [ "$valid_hash" = "n" ]; then die "!!! Missing required boot hashes" fi - if [ "$CONFIG_TPM" = "y" ] && [ -r "$TMP_KEY_DEVICES" ]; then + if [ "$CONFIG_BASIC" != y ] && [ "$CONFIG_TPM" = "y" ] && [ -r "$TMP_KEY_DEVICES" ]; then INITRD=`kexec-boot -b "$bootdir" -e "$option" -i` \ || die "!!! Failed to extract the initrd from boot option" if [ -z "$INITRD" ]; then @@ -342,7 +349,7 @@ do_boot() } while true; do - if [ "$force_boot" = "y" ]; then + if [ "$force_boot" = "y" -o "$CONFIG_BASIC" = "y" ]; then check_config $paramsdir force else check_config $paramsdir @@ -360,9 +367,11 @@ while true; do # even if hashes don't match if [ "$force_boot" = "y" ]; then scan_options - # Remove boot splash and make background red in the event of a forced boot - add="$add vt.default_red=0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff" - remove="$remove splash quiet" + if [ "$CONFIG_BASIC" != "y" ]; then + # Remove boot splash and make background red in the event of a forced boot + add="$add vt.default_red=0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff" + remove="$remove splash quiet" + fi user_select fi @@ -379,7 +388,7 @@ while true; do scan_options fi - if [ "$CONFIG_TPM" = "y" ]; then + if [ "$CONFIG_BASIC" != "y" ]; then # Optionally enforce device file hashes if [ -r "$TMP_HASH_FILE" ]; then valid_global_hash="n" diff --git a/initrd/bin/media-scan b/initrd/bin/media-scan index d64be05d9..4a23a9340 100755 --- a/initrd/bin/media-scan +++ b/initrd/bin/media-scan @@ -42,8 +42,10 @@ get_menu_option() { MENU_OPTIONS="$MENU_OPTIONS $n ${option}" done < /tmp/iso_menu.txt + MENU_OPTIONS="$MENU_OPTIONS a Abort" + whiptail $BG_COLOR_MAIN_MENU --title "Select your ISO boot option" \ - --menu "Choose the ISO boot option [1-$n, s for standard boot, a to abort]:" 0 80 8 \ + --menu "Choose the ISO boot option [1-$n]:" 0 80 8 \ -- $MENU_OPTIONS \ 2>/tmp/whiptail || die "Aborting boot attempt" @@ -58,20 +60,20 @@ get_menu_option() { done < /tmp/iso_menu.txt read \ - -p "Choose the ISO boot option [1-$n, s for standard boot, a to abort]: " \ + -p "Choose the ISO boot option [1-$n, a to abort]: " \ option_index fi - if [ "$option_index" = "a" ]; then + # Empty occurs when aborting fbwhiptail with esc-esc + if [ -z "$option_index" ] || [ "$option_index" = "a" ]; then die "Aborting boot attempt" fi - if [ "$option_index" = "s" ]; then - option="" - return - fi - option=`head -n $option_index /tmp/iso_menu.txt | tail -1` + + if [ -z "$option" ]; then + die "Failed to find menu option $option_index" + fi } # create ISO menu options @@ -83,13 +85,17 @@ if [ `cat /tmp/iso_menu.txt | wc -l` -gt 0 ]; then get_menu_option done - if [ -n "$option" ]; then - MOUNTED_ISO=$option - ISO=${option:7} # remove /media/ to get device relative path - DO_WITH_DEBUG kexec-iso-init $MOUNTED_ISO $ISO $USB_BOOT_DEV + MOUNTED_ISO="$option" + ISO="${option:7}" # remove /media/ to get device relative path + DO_WITH_DEBUG kexec-iso-init "$MOUNTED_ISO" "$ISO" "$USB_BOOT_DEV" - die "Something failed in iso init" - fi + die "Something failed in iso init" +fi + +# No *.iso files on media, try ordinary bootable USB + +if [ "$CONFIG_RESTRICTED_BOOT" = y ]; then + die "No ISO files found, bootable USB not allowed with Restricted Boot." fi echo "!!! Could not find any ISO, trying bootable USB" diff --git a/initrd/bin/mount-usb b/initrd/bin/mount-usb index 70b1c0978..35e81f07f 100755 --- a/initrd/bin/mount-usb +++ b/initrd/bin/mount-usb @@ -5,18 +5,7 @@ TRACE "Under /bin/mount-usb" enable_usb - -if ! lsmod | grep -q usb_storage; then - timeout=0 - echo "Scanning for USB storage devices..." - insmod /lib/modules/usb-storage.ko >/dev/null 2>&1 \ - || die "usb_storage: module load failed" - while [[ $(list_usb_storage | wc -l) -eq 0 ]]; do - [[ $timeout -ge 8 ]] && break - sleep 1 - timeout=$(($timeout+1)) - done -fi +enable_usb_storage if [ ! -d /media ]; then mkdir /media @@ -26,7 +15,7 @@ list_usb_storage > /tmp/usb_block_devices if [ -z "$(cat /tmp/usb_block_devices)" ]; then if [ -x /bin/whiptail ]; then whiptail $BG_COLOR --title 'USB Drive Missing' \ - --msgbox "Insert your USB drive and press Enter to continue." 16 60 + --msgbox "Insert your USB drive and press Enter to continue." 0 80 else echo "+++ USB Drive Missing! Insert your USB drive and press Enter to continue." read @@ -36,7 +25,7 @@ if [ -z "$(cat /tmp/usb_block_devices)" ]; then if [ -z "$(cat /tmp/usb_block_devices)" ]; then if [ -x /bin/whiptail ]; then whiptail $BG_COLOR_ERROR --title 'ERROR: USB Drive Missing' \ - --msgbox "USB Drive Missing! Aborting mount attempt.\n\nPress Enter to continue." 16 60 + --msgbox "USB Drive Missing! Aborting mount attempt.\n\nPress Enter to continue." 0 80 else echo "!!! ERROR: USB Drive Missing! Aborting mount. Press Enter to continue." fi diff --git a/initrd/bin/oem-factory-reset b/initrd/bin/oem-factory-reset index 639eb8610..9c90732fc 100755 --- a/initrd/bin/oem-factory-reset +++ b/initrd/bin/oem-factory-reset @@ -392,146 +392,151 @@ fi # We show current integrity measurements status and time report_integrity_measurements -# Re-ownership of encrypted disk key, content and passphrase -echo -e -n "Would you like to change the current LUKS Disk Recovery Key passphrase?\n (Highly recommended if you didn't install the Operating System yourself, so that past provisioned passphrase would not permit to access content.\n Note that without re-encrypting disk, a backuped header could be restored to access encrypted content with old passphrase) [y/N]: " -read -n 1 prompt_output -echo -if [ "$prompt_output" == "y" \ - -o "$prompt_output" == "Y" ];then - luks_new_Disk_Recovery_Key_passphrase_desired=1 - echo -e "\n" -fi +use_defaults=n +if [ "$CONFIG_OEMRESET_OFFER_DEFAULTS" = y ]; then + echo -e -n "Would you like to use default configuration options?\nIf N, you will be prompted for each option [Y/n]: " + read -n 1 use_defaults +fi + +if [ "$use_defaults" == "n" -o "$use_defaults" == "N" ]; then + # Re-ownership of encrypted disk key, content and passphrase + echo -e -n "\n\nWould you like to change the current LUKS Disk Recovery Key passphrase?\n (Highly recommended if you didn't install the Operating System yourself, so that past provisioned passphrase would not permit to access content.\n Note that without re-encrypting disk, a backuped header could be restored to access encrypted content with old passphrase) [y/N]: " + read -n 1 prompt_output + echo + if [ "$prompt_output" == "y" \ + -o "$prompt_output" == "Y" ];then + luks_new_Disk_Recovery_Key_passphrase_desired=1 + echo -e "\n" + fi -echo -e -n "Would you like to re-encrypt LUKS encrypted container and generate new Disk Recovery key?\n (Highly recommended if you didn't install the operating system yourself: this would prevent any LUKS backuped header to be restored to access encrypted data) [y/N]: " -read -n 1 prompt_output -echo -if [ "$prompt_output" == "y" \ - -o "$prompt_output" == "Y" ];then - test_luks_current_disk_recovery_key_passphrase - luks_new_Disk_Recovery_Key_desired=1 - echo -e "\n" -fi + echo -e -n "Would you like to re-encrypt LUKS encrypted container and generate new Disk Recovery key?\n (Highly recommended if you didn't install the operating system yourself: this would prevent any LUKS backuped header to be restored to access encrypted data) [y/N]: " + read -n 1 prompt_output + echo + if [ "$prompt_output" == "y" \ + -o "$prompt_output" == "Y" ];then + test_luks_current_disk_recovery_key_passphrase + luks_new_Disk_Recovery_Key_desired=1 + echo -e "\n" + fi -# Adapt message to be given to user in terms of security components that will be applied. -if [ -n "$luks_new_Disk_Recovery_Key_passphrase_desired" -o -n "$luks_new_Disk_Recovery_Key_passphrase" ]; then - CUSTOM_PASS_AFFECTED_COMPONENTS="LUKS Disk Recovery Key passphrase" -fi -if [ "$CONFIG_TPM" = "y" ]; then - CUSTOM_PASS_AFFECTED_COMPONENTS="$CUSTOM_PASS_AFFECTED_COMPONENTS + # Adapt message to be given to user in terms of security components that will be applied. + if [ -n "$luks_new_Disk_Recovery_Key_passphrase_desired" -o -n "$luks_new_Disk_Recovery_Key_passphrase" ]; then + CUSTOM_PASS_AFFECTED_COMPONENTS="LUKS Disk Recovery Key passphrase" + fi + if [ "$CONFIG_TPM" = "y" ]; then + CUSTOM_PASS_AFFECTED_COMPONENTS="$CUSTOM_PASS_AFFECTED_COMPONENTS TPM Ownership password" -fi -CUSTOM_PASS_AFFECTED_COMPONENTS="$CUSTOM_PASS_AFFECTED_COMPONENTS + fi + CUSTOM_PASS_AFFECTED_COMPONENTS="$CUSTOM_PASS_AFFECTED_COMPONENTS GPG Admin PIN GPG User PIN" -# Inform user of security components affected for the following prompts -echo -e "The following security components will be provisioned with defaults or chosen PINs/passwords: -$CUSTOM_PASS_AFFECTED_COMPONENTS\n" + # Inform user of security components affected for the following prompts + echo -e "The following security components will be provisioned with defaults or chosen PINs/passwords: + $CUSTOM_PASS_AFFECTED_COMPONENTS\n" + + # Prompt to change default passwords + echo -e -n "Would you like to set a single custom password that will be provisioned to previously stated security components? [y/N]: " + read -n 1 prompt_output + echo + if [ "$prompt_output" == "y" \ + -o "$prompt_output" == "Y" ]; then + echo -e "\nThe chosen custom password must be between 8 and $MAX_HOTP_GPG_PIN_LENGTH characters in length.\n" + echo + while [[ ${#CUSTOM_SINGLE_PASS} -lt 8 ]] || [[ ${#CUSTOM_SINGLE_PASS} -gt $MAX_HOTP_GPG_PIN_LENGTH ]] ; do + echo -e -n "Enter the custom password: " + read CUSTOM_SINGLE_PASS + done + echo + TPM_PASS=$CUSTOM_SINGLE_PASS + USER_PIN=$CUSTOM_SINGLE_PASS + ADMIN_PIN=$CUSTOM_SINGLE_PASS + + # Only set if user said desired. Matches rest of logic + if [ -n "$luks_new_Disk_Recovery_Key_passphrase_desired" ]; then + luks_new_Disk_Recovery_Key_passphrase=$CUSTOM_SINGLE_PASS + fi + else + echo -e -n "Would you like to set distinct PINs/passwords to be provisioned to previously stated security components? [y/N]: " + read -n 1 prompt_output + echo + if [ "$prompt_output" == "y" \ + -o "$prompt_output" == "Y" ]; then + echo -e "\nThey must be each at least 8 characters in length.\n" + echo + if [ "$CONFIG_TPM" = "y" ]; then + while [[ ${#TPM_PASS} -lt 8 ]] ; do + echo -e -n "Enter desired TPM Ownership password: " + read TPM_PASS + done + fi + while [[ ${#ADMIN_PIN} -lt 8 ]] || [[ ${#ADMIN_PIN} -gt $MAX_HOTP_GPG_PIN_LENGTH ]] ; do + echo -e -n "\nThis PIN should be between 8 to $MAX_HOTP_GPG_PIN_LENGTH characters in length.\n" + echo -e -n "Enter desired GPG Admin PIN: " + read ADMIN_PIN + done + while [[ ${#USER_PIN} -lt 8 ]] || [[ ${#USER_PIN} -gt 64 ]]; do + echo -e -n "\nThis PIN should be between 8 to 64 characters in length.\n" + echo -e -n "Enter desired GPG User PIN: " + read USER_PIN + done + echo + fi + fi -# Prompt to change default passwords -echo -e -n "Would you like to set a single custom password that will be provisioned to previously stated security components? [y/N]: " -read -n 1 prompt_output -echo -if [ "$prompt_output" == "y" \ - -o "$prompt_output" == "Y" ] \ -; then - echo -e "\nThe chosen custom password must be between 8 and $MAX_HOTP_GPG_PIN_LENGTH characters in length.\n" - echo - while [[ ${#CUSTOM_SINGLE_PASS} -lt 8 ]] || [[ ${#CUSTOM_SINGLE_PASS} -gt $MAX_HOTP_GPG_PIN_LENGTH ]] ; do - echo -e -n "Enter the custom password: " - read CUSTOM_SINGLE_PASS - done - echo - TPM_PASS=$CUSTOM_SINGLE_PASS - USER_PIN=$CUSTOM_SINGLE_PASS - ADMIN_PIN=$CUSTOM_SINGLE_PASS - - # Only set if user said desired. Matches rest of logic - if [ -n "$luks_new_Disk_Recovery_Key_passphrase_desired" ]; then - luks_new_Disk_Recovery_Key_passphrase=$CUSTOM_SINGLE_PASS + if [ -n "$luks_new_Disk_Recovery_Key_passphrase_desired" -a -z "$luks_new_Disk_Recovery_Key_passphrase" ]; then + # We catch here if changing LUKS Disk Recovery Key passphrase was desired + # but yet undone. This is if not being covered by the single password + echo -e "\nEnter desired replacement for current Disk Recovery Key passphrase (At least 8 characters long):" + while [[ ${#luks_new_Disk_Recovery_Key_passphrase} -lt 8 ]]; do + { + read -r luks_new_Disk_Recovery_Key_passphrase + };done + #We test that current Disk Recovery Key passphrase is known prior of going further + test_luks_current_disk_recovery_key_passphrase + echo -e "\n" fi -else - echo -e -n "Would you like to set distinct PINs/passwords to be provisioned to previously stated security components? [y/N]: " - read -n 1 prompt_output - echo - if [ "$prompt_output" == "y" \ - -o "$prompt_output" == "Y" ] \ - ; then - echo -e "\nThey must be each at least 8 characters in length.\n" - echo - if [ "$CONFIG_TPM" = "y" ]; then - while [[ ${#TPM_PASS} -lt 8 ]] ; do - echo -e -n "Enter desired TPM Ownership password: " - read TPM_PASS - done - fi - while [[ ${#ADMIN_PIN} -lt 8 ]] || [[ ${#ADMIN_PIN} -gt $MAX_HOTP_GPG_PIN_LENGTH ]] ; do - echo -e -n "\nThis PIN should be between 8 to $MAX_HOTP_GPG_PIN_LENGTH characters in length.\n" - echo -e -n "Enter desired GPG Admin PIN: " - read ADMIN_PIN - done - while [[ ${#USER_PIN} -lt 8 ]] || [[ ${#USER_PIN} -gt 64 ]]; do - echo -e -n "\nThis PIN should be between 8 to 64 characters in length.\n" - echo -e -n "Enter desired GPG User PIN: " - read USER_PIN - done - echo - fi -fi -if [ -n "$luks_new_Disk_Recovery_Key_passphrase_desired" -a -z "$luks_new_Disk_Recovery_Key_passphrase" ]; then - # We catch here if changing LUKS Disk Recovery Key passphrase was desired - # but yet undone. This is if not being covered by the single password - echo -e "\nEnter desired replacement for current Disk Recovery Key passphrase (At least 8 characters long):" - while [[ ${#luks_new_Disk_Recovery_Key_passphrase} -lt 8 ]]; do - { - read -r luks_new_Disk_Recovery_Key_passphrase - };done - #We test that current Disk Recovery Key passphrase is known prior of going further - test_luks_current_disk_recovery_key_passphrase - echo -e "\n" -fi + # Prompt to change default GnuPG key information + echo -e -n "Would you like to set custom user information for the GnuPG key? [y/N]: " + read -n 1 prompt_output + echo + if [ "$prompt_output" == "y" \ + -o "$prompt_output" == "Y" ]; then + echo -e "\n\n" + echo -e "We will generate a GnuPG (PGP) keypair identifiable with the following text form:" + echo -e "Real Name (Comment) email@address.org" -# If nothing is stored in custom variables, we set them to their defaults -if [ "$TPM_PASS" == "" ]; then TPM_PASS=$TPM_PASS_DEF; fi -if [ "$USER_PIN" == "" ]; then USER_PIN=$USER_PIN_DEF; fi -if [ "$ADMIN_PIN" == "" ]; then ADMIN_PIN=$ADMIN_PIN_DEF; fi + echo -e "\nEnter your Real Name (Optional):" + read -r GPG_USER_NAME -# Prompt to change default GnuPG key information -echo -e -n "Would you like to set custom user information for the GnuPG key? [y/N]: " -read -n 1 prompt_output -echo -if [ "$prompt_output" == "y" \ - -o "$prompt_output" == "Y" ] \ -; then - echo -e "\n\n" - echo -e "We will generate a GnuPG (PGP) keypair identifiable with the following text form:" - echo -e "Real Name (Comment) email@address.org" - - echo -e "\nEnter your Real Name (Optional):" - read -r GPG_USER_NAME - - echo -e "\nEnter your email@adress.org:" - read -r GPG_USER_MAIL - while ! $(expr "$GPG_USER_MAIL" : '.*@' >/dev/null); do - { - echo -e "\nEnter your email@address.org:" + echo -e "\nEnter your email@adress.org:" read -r GPG_USER_MAIL - };done + while ! $(expr "$GPG_USER_MAIL" : '.*@' >/dev/null); do + { + echo -e "\nEnter your email@address.org:" + read -r GPG_USER_MAIL + };done - echo -e "\nEnter Comment (Optional, to distinguish this key from others with same previous attributes. Must be smaller then 60 characters):" - read -r GPG_USER_COMMENT - while [[ ${#GPG_USER_COMMENT} -gt 60 ]]; do - { echo -e "\nEnter Comment (Optional, to distinguish this key from others with same previous attributes. Must be smaller then 60 characters):" read -r GPG_USER_COMMENT - };done -fi + while [[ ${#GPG_USER_COMMENT} -gt 60 ]]; do + { + echo -e "\nEnter Comment (Optional, to distinguish this key from others with same previous attributes. Must be smaller then 60 characters):" + read -r GPG_USER_COMMENT + };done + fi +fi + +# If nothing is stored in custom variables, we set them to their defaults +if [ "$TPM_PASS" == "" ]; then TPM_PASS=$TPM_PASS_DEF; fi +if [ "$USER_PIN" == "" ]; then USER_PIN=$USER_PIN_DEF; fi +if [ "$ADMIN_PIN" == "" ]; then ADMIN_PIN=$ADMIN_PIN_DEF; fi ## sanity check the USB, GPG key, and boot device before proceeding further # Prompt to insert USB drive if desired -echo -e -n "Would you like to export your public key to an USB drive? [y/N]: " +echo -e -n "\nWould you like to export your public key to an USB drive? [y/N]: " read -n 1 prompt_output echo if [ "$prompt_output" == "y" \ diff --git a/initrd/bin/root-hashes-gui.sh b/initrd/bin/root-hashes-gui.sh new file mode 100755 index 000000000..d4bcab448 --- /dev/null +++ b/initrd/bin/root-hashes-gui.sh @@ -0,0 +1,303 @@ +#!/bin/bash + +set -e -o pipefail + +CONFIG_ROOT_DIRLIST="bin boot lib sbin usr" +HASH_FILE="/boot/kexec_root_hashes.txt" +ROOT_MOUNT="/root" + +. /etc/functions +. /etc/gui_functions +. /tmp/config + +export CONFIG_ROOT_DIRLIST_PRETTY=$(echo $CONFIG_ROOT_DIRLIST | sed -e 's/^/\//;s/ / \//g') + +update_root_checksums() { + if ! detect_root_device; then + whiptail $BG_COLOR_ERROR --title 'ERROR: No Valid Root Disk Found' \ + --msgbox "No Valid Root Disk Found" 0 80 + die "No Valid Root Disk Found" + fi + + # mount /boot RW + if ! grep -q /boot /proc/mounts ; then + if ! mount -o rw /boot; then + unmount_root_device + whiptail $BG_COLOR_ERROR --title 'ERROR: Unable to mount /boot' \ + --msgbox "Unable to mount /boot" 0 80 + die "Unable to mount /boot" + fi + else + mount -o rw,remount /boot + fi + + echo "+++ Calculating hashes for all files in $CONFIG_ROOT_DIRLIST_PRETTY " + cd $ROOT_MOUNT && find ${CONFIG_ROOT_DIRLIST} -type f ! -name '*kexec*' -print0 | xargs -0 sha256sum | tee ${HASH_FILE} + + # switch back to ro mode + mount -o ro,remount /boot + + update_checksums + + whiptail --title 'Root Hashes Updated and Signed' \ + --msgbox "All files in:\n$CONFIG_ROOT_DIRLIST_PRETTY\nhave been hashed and signed successfully" 0 80 + + unmount_root_device +} +check_root_checksums() { + if ! detect_root_device; then + whiptail $BG_COLOR_ERROR --title 'ERROR: No Valid Root Disk Found' \ + --msgbox "No Valid Root Disk Found" 0 80 + die "No Valid Root Disk Found" + fi + + # mount /boot RO + if ! grep -q /boot /proc/mounts ; then + if ! mount -o ro /boot; then + unmount_root_device + whiptail $BG_COLOR_ERROR --title 'ERROR: Unable to mount /boot' \ + --msgbox "Unable to mount /boot" 0 80 + die "Unable to mount /boot" + fi + fi + + # check that root hash file exists + if [ ! -f ${HASH_FILE} ]; then + if (whiptail $BG_COLOR_WARNING --title 'WARNING: No Root Hash File Found' \ + --yesno "\nIf you just enabled root hash checking feature, + \nthen you need to create the initial hash file. + \nOtherwise, This could be caused by tampering. + \n + \nWould you like to create the hash file now?" 0 80) then + update_root_checksums + return 0 + else + exit 1 + fi + fi + + echo "+++ Checking root hash file signature " + if ! sha256sum `find /boot/kexec*.txt` | gpgv /boot/kexec.sig - > /tmp/hash_output; then + ERROR=`cat /tmp/hash_output` + whiptail $BG_COLOR_ERROR --title 'ERROR: Signature Failure' \ + --msgbox "The signature check on hash files failed:\n${CHANGED_FILES}\nExiting to a recovery shell" 0 80 + unmount_root_device + die 'Invalid signature' + fi + + echo "+++ Checking for new files in $CONFIG_ROOT_DIRLIST_PRETTY " + find ${CONFIG_ROOT_DIRLIST} -type f ! -name '*kexec*' | sort > /tmp/new_file_list + cut -d' ' -f3- ${HASH_FILE} | sort | diff -U0 - /tmp/new_file_list > /tmp/new_file_diff || new_files_found=y + if [ "$new_files_found" == "y" ]; then + grep -E -v '^[+-]{3}|[@]{2} ' /tmp/new_file_diff > /tmp/new_file_diff2 # strip any output that's not a file + mv /tmp/new_file_diff2 /tmp/new_file_diff + CHANGED_FILES_COUNT=$(wc -l /tmp/new_file_diff | cut -f1 -d ' ') + whiptail $BG_COLOR_ERROR --title 'ERROR: Files Added/Removed in Root ' \ + --msgbox "${CHANGED_FILES_COUNT} files were added/removed in root!\n\nHit OK to review the list of files.\n\nType \"q\" to exit the list and return to the menu." 0 80 + + echo "Type \"q\" to exit the list and return to the menu." >> /tmp/new_file_diff + less /tmp/new_file_diff + else + echo "+++ Verified no files added/removed " + fi + + echo "+++ Checking hashes for all files in $CONFIG_ROOT_DIRLIST_PRETTY (this might take a while) " + if cd $ROOT_MOUNT && sha256sum -c ${HASH_FILE} > /tmp/hash_output 2>/dev/null; then + echo "+++ Verified root hashes " + valid_hash='y' + unmount_root_device + + if [ "$new_files_found" == "y" ]; then + if (whiptail --title 'ERROR: New Files Added/Removed in Root' \ + --yesno "New files were added/removed in root. + \n + \nThis could be caused by tampering or by routine software updates. + \n + \nIf you just updated the software on your system, then that is likely + \nthe cause and you should update your file signatures. + \n + \nWould you like to update your signatures now?" 0 80) then + + update_root_checksums + + return 0 + else + return 1 + fi + fi + return 0 + else + CHANGED_FILES=$(grep -v 'OK$' /tmp/hash_output | cut -f1 -d ':' | tee -a /tmp/hash_output_mismatches) + CHANGED_FILES_COUNT=$(wc -l /tmp/hash_output_mismatches | cut -f1 -d ' ') + whiptail $BG_COLOR_ERROR --title 'ERROR: Root Hash Mismatch' \ + --msgbox "${CHANGED_FILES_COUNT} files failed the verification process!\n\nHit OK to review the list of files.\n\nType \"q\" to exit the list and return to the menu." 0 80 + unmount_root_device + + echo "Type \"q\" to exit the list and return to the menu." >> /tmp/hash_output_mismatches + less /tmp/hash_output_mismatches + + #move outdated hash mismatch list + mv /tmp/hash_output_mismatches /tmp/hash_output_mismatch_old + + if (whiptail --title 'ERROR: Root Hash Check Failed' \ + --yesno "The root hash check failed. + \n + \nThis could be caused by tampering or by routine software updates. + \n + \nIf you just updated the software on your system, then that is likely + \nthe cause and you should update your file signatures. + \n + \nWould you like to update your signatures now?" 0 80) then + + update_root_checksums + return 0 + else + return 1 + fi + fi +} +# detect and set /root device +# mount /root if successful +detect_root_device() +{ + echo "+++ Detecting root device " + + if [ ! -e $ROOT_MOUNT ]; then + mkdir -p $ROOT_MOUNT + fi + # unmount $ROOT_MOUNT to be safe + cd / && umount $ROOT_MOUNT 2>/dev/null + + # check $CONFIG_ROOT_DEV if set/valid + if [ -e "$CONFIG_ROOT_DEV" ]; then + if cryptsetup isLuks $CONFIG_ROOT_DEV >/dev/null 2>&1; then + if cryptsetup luksOpen $CONFIG_ROOT_DEV rootdisk; then + if mount -o ro /dev/mapper/rootdisk $ROOT_MOUNT >/dev/null 2>&1; then + if cd $ROOT_MOUNT && ls -d $CONFIG_ROOT_DIRLIST >/dev/null 2>&1; then # CONFIG_ROOT_DEV is valid device and contains an installed OS + return 0 + fi + fi + fi + fi + fi + + # generate list of possible boot devices + fdisk -l | grep "Disk /dev/" | cut -f2 -d " " | cut -f1 -d ":" > /tmp/disklist + + # filter out extraneous options + > /tmp_root_device_list + for i in `cat /tmp/disklist`; do + # remove block device from list if numeric partitions exist + DEV_NUM_PARTITIONS=$((`ls -1 $i* | wc -l`-1)) + if [ ${DEV_NUM_PARTITIONS} -eq 0 ]; then + echo $i >> /tmp_root_device_list + else + ls $i* | tail -${DEV_NUM_PARTITIONS} >> /tmp_root_device_list + fi + done + + # iterate thru possible options and check for LUKS + for i in `cat /tmp_root_device_list`; do + if cryptsetup isLuks $i >/dev/null 2>&1; then + if cryptsetup luksOpen $i rootdisk; then + if mount -o ro /dev/mapper/rootdisk $ROOT_MOUNT >/dev/null 2>&1; then + if cd $ROOT_MOUNT && ls -d $CONFIG_ROOT_DIRLIST >/dev/null 2>&1; then + # CONFIG_ROOT_DEV is valid device and contains an installed OS + CONFIG_ROOT_DEV="$i" + return 0 + fi + fi + fi + fi + done + + # no valid root device found + echo "Unable to locate $ROOT_MOUNT files on any mounted disk" + unmount_root_device + return 1 +} +unmount_root_device() +{ + cd / + umount $ROOT_MOUNT 2>/dev/null + cryptsetup luksClose rootdisk +} + +checkonly="n" +createnew="n" +while getopts ":hcn" arg; do + case $arg in + c) checkonly="y" ;; + n) createnew="y" ;; + h) echo "Usage: $0 [-c|-h|-n]"; exit 0 ;; + esac +done + +if [ "$checkonly" = "y" ]; then + check_root_checksums + if [ -e /tmp/hash_output_mismatches ]; then # if this file exists, there were errors + exit 1 + else + exit 0 + fi +fi + +if [ "$createnew" = "y" ]; then + update_root_checksums + exit 0 +fi + +while true; do + unset menu_choice + + # mount /boot RO to detect hash file + if ! grep -q /boot /proc/mounts ; then + if ! mount -o ro /boot; then + unmount_root_device + whiptail $BG_COLOR_ERROR --title 'ERROR: Unable to mount /boot' \ + --msgbox "Unable to mount /boot" 0 80 + die "Unable to mount /boot" + fi + fi + + if [ "$CONFIG_ROOT_CHECK_AT_BOOT" = "y" ]; then + AT_BOOT="enabled" + else + AT_BOOT="disabled" + fi + if [ -e "$HASH_FILE" ]; then + HASH_FILE_DATE=$(stat -c %y ${HASH_FILE}) + whiptail --title "Root Disk Verification Menu" \ + --menu "This feature lets you detect tampering in files on your root disk.\n\nHash file last updated: ${HASH_FILE_DATE}\n\nYou can check and update hashes for files in:\n $CONFIG_ROOT_DIRLIST_PRETTY\n\nAutomatic checks are ${AT_BOOT} at boot.\n\nSelect the function to perform:" 0 80 10 \ + 'c' ' Check root hashes' \ + 'u' ' Update root hashes' \ + 'x' ' Exit' \ + 2>/tmp/whiptail || recovery "GUI menu failed" + else + whiptail --title "Root Disk Verification Menu" \ + --menu "This feature lets you detect tampering in files on your root disk.\n\nNo hash file has been created yet\n\nYou can create hashes for files in:\n $CONFIG_ROOT_DIRLIST_PRETTY\n\nAutomatic checks are ${AT_BOOT} at boot.\n\nSelect the function to perform:" 0 80 10 \ + 'u' ' Create root hashes' \ + 'x' ' Exit' \ + 2>/tmp/whiptail || recovery "GUI menu failed" + fi + + menu_choice=$(cat /tmp/whiptail) + + case "$menu_choice" in + "x" ) + exit 0 + ;; + "c" ) + check_root_checksums + if [ $? -eq 0 ]; then + whiptail --title 'Verified Root Hashes' \ + --msgbox "All files in $CONFIG_ROOT_DIRLIST_PRETTY passed the verification process" 0 80 + fi + ;; + "u" ) + update_root_checksums + ;; + esac + +done +exit 0 diff --git a/initrd/bin/seal-hotpkey b/initrd/bin/seal-hotpkey index 7e8cc75b4..d206ada15 100755 --- a/initrd/bin/seal-hotpkey +++ b/initrd/bin/seal-hotpkey @@ -19,6 +19,13 @@ mount_boot() TRACE "Under /bin/seal-hotpkey" +fatal_error() +{ + echo -e "\nERROR: ${1}; press Enter to continue." + read + die "$1" +} + # Use stored HOTP key branding (this might be useful after OEM reset) if [ -r /boot/kexec_hotp_key ]; then HOTPKEY_BRANDING="$(cat /boot/kexec_hotp_key)" @@ -29,7 +36,10 @@ fi if [ "$CONFIG_TPM" = "y" ]; then DEBUG "Sealing HOTP secret reuses TOTP sealed secret..." tpmr unseal 4d47 0,1,2,3,4,7 312 "$HOTP_SECRET" \ - || die "Unable to unseal HOTP secret" + || fatal_error "Unable to unseal HOTP secret" +else + # without a TPM, generate a secret based on the SHA-256 of the ROM + secret_from_rom_hash > "$HOTP_SECRET" || die "Reading ROM failed" fi # Store counter in file instead of TPM for now, as it conflicts with Heads @@ -51,13 +61,15 @@ mount_boot counter_value=1 enable_usb -if ! hotp_verification info ; then - echo "Insert your $HOTPKEY_BRANDING and press Enter to configure it" +# While making sure the key is inserted, capture the status so we can check how +# many PIN attempts remain +if ! hotp_token_info="$(hotp_verification info)" ; then + echo -e "\nInsert your $HOTPKEY_BRANDING and press Enter to configure it" read - if ! hotp_verification info ; then + if ! hotp_token_info="$(hotp_verification info)" ; then # don't leak key on failure shred -n 10 -z -u "$HOTP_SECRET" 2> /dev/null - die "Unable to find $HOTPKEY_BRANDING" + fatal_error "Unable to find $HOTPKEY_BRANDING" fi fi @@ -70,20 +82,63 @@ else HOTPKEY_BRANDING="HOTP USB Security Dongle" fi -echo -e "" -read -s -p "Enter your $HOTPKEY_BRANDING Admin PIN: " admin_pin -echo -e "\n" +# Truncate the secret if it is longer than the maximum HOTP secret +truncate_max_bytes 20 "$HOTP_SECRET" + +# Check when the signing key was created to consider trying the default PIN +# (Note: we must avoid using gpg --card-status here as the Nitrokey firmware +# locks up, https://github.com/Nitrokey/nitrokey-pro-firmware/issues/54) +gpg_key_create_time="$(gpg --list-keys --with-colons | grep -m 1 '^pub:' | cut -d: -f6)" +gpg_key_create_time="${gpg_key_create_time:-0}" +DEBUG "Signature key was created at $(date -d "@$gpg_key_create_time")" +now_date="$(date '+%s')" + +# Get the number of admin PIN retry attempts remaining +awk_admin_counter_regex='/^\s*Card counters: Admin (\d),.*$/' +awk_get_admin_counter="$awk_admin_counter_regex"' { print gensub('"$awk_admin_counter_regex"', "\\1", "") }' +admin_pin_retries="$(echo "$hotp_token_info" | awk "$awk_get_admin_counter")" +admin_pin_retries="${admin_pin_retries:-0}" +DEBUG "Admin PIN retry counter is $admin_pin_retries" + +# Try using factory default admin PIN for 1 month following OEM reset to ease +# initial setup. But don't do it forever to encourage changing the PIN and +# so PIN attempts are not consumed by the default attempt. +admin_pin="12345678" +month_secs="$((30*24*60*60))" +admin_pin_status=1 +if [ "$((now_date - gpg_key_create_time))" -gt "$month_secs" ]; then + # Remind what the default PIN was in case it still hasn't been changed + echo "Not trying default PIN ($admin_pin)" +# Never consume an attempt if there are less than 3 attempts left, otherwise +# attempting the default PIN could cause an unexpected lockout before getting a +# chance to enter the correct PIN +elif [ "$admin_pin_retries" -lt 3 ]; then + echo "Not trying default PIN ($admin_pin), only $admin_pin_retries attempt(s) left" +else + hotp_initialize "$admin_pin" $HOTP_SECRET $counter_value "$HOTPKEY_BRANDING" >/dev/null 2>&1 + admin_pin_status="$?" +fi -hotp_initialize "$admin_pin" $HOTP_SECRET $counter_value "$HOTPKEY_BRANDING" -if [ $? -ne 0 ]; then - echo -e "\n" - read -s -p "Error setting HOTP secret, re-enter Admin PIN and try again: " admin_pin +if [ "$admin_pin_status" -ne 0 ]; then + # prompt user for PIN and retry + echo "" + read -s -p "Enter your $HOTPKEY_BRANDING Admin PIN: " admin_pin echo -e "\n" - if ! hotp_initialize "$admin_pin" $HOTP_SECRET $counter_value "$HOTPKEY_BRANDING" ; then - # don't leak key on failure - shred -n 10 -z -u "$HOTP_SECRET" 2> /dev/null - die "Setting HOTP secret failed" + + hotp_initialize "$admin_pin" $HOTP_SECRET $counter_value "$HOTPKEY_BRANDING" + if [ $? -ne 0 ]; then + echo -e "\n" + read -s -p "Error setting HOTP secret, re-enter Admin PIN and try again: " admin_pin + echo -e "\n" + if ! hotp_initialize "$admin_pin" $HOTP_SECRET $counter_value "$HOTPKEY_BRANDING" ; then + # don't leak key on failure + shred -n 10 -z -u "$HOTP_SECRET" 2> /dev/null + fatal_error "Setting HOTP secret failed" + fi fi +else + # remind user to change admin password + echo -e "\nWARNING: default GPG admin PIN detected: please change this as soon as possible." fi # HOTP key no longer needed @@ -99,7 +154,7 @@ mount -o remount,rw /boot counter_value=`expr $counter_value + 1` echo $counter_value > $HOTP_COUNTER \ -|| die "Unable to create hotp counter file" +|| fatal_error "Unable to create hotp counter file" # Store/overwrite HOTP USB Security Dongle branding found out beforehand echo $HOTPKEY_BRANDING > $HOTP_KEY \ diff --git a/initrd/bin/tpmr b/initrd/bin/tpmr index a513a93ce..1e5a19ad8 100755 --- a/initrd/bin/tpmr +++ b/initrd/bin/tpmr @@ -351,6 +351,32 @@ cleanup_shred() { shred -n 10 -z -u "$1" 2>/dev/null || true } +# tpm2_destroy: Destroy a sealed file in the TPM. The mechanism differs by +# TPM version - TPM2 evicts the file object, so it no longer exists. +tpm2_destroy() { + index="$1" # Index of the sealed file + size="$2" # Size of zeroes to overwrite for TPM1 (unused in TPM2) + + # Pad with up to 6 zeros, i.e. '0x81000001', '0x81001234', etc. + handle="$(printf "0x81%6s" "$index" | tr ' ' 0)" + + # remove possible data occupying this handle + tpm2 evictcontrol -Q -C p -c "$handle" 2>/dev/null \ + || die "Unable to evict secret" +} + +# tpm1_destroy: Destroy a sealed file in the TPM. The mechanism differs by +# TPM version - TPM1 overwrites the file with zeroes, since this can be done +# without authorization. (Deletion requires authorization.) +tpm1_destroy() { + index="$1" # Index of the sealed file + size="$2" # Size of zeroes to overwrite for TPM1 + + dd if=/dev/zero bs="$size" count=1 of=/tmp/wipe-totp-zero + tpm nv_writevalue -in "$index" -if /tmp/wipe-totp-zero \ + || die "Unable to wipe sealed secret" +} + # tpm2_seal: Seal a file against PCR values and, optionally, a password. # If a password is given, both the PCRs and password are required to unseal the # file. PCRs are provided as a PCR list and data file. PCR data must be @@ -677,6 +703,8 @@ if [ "$CONFIG_TPM2_TOOLS" != "y" ]; then echo "$PCR_SIZE";; calcfuturepcr) shift; replay_pcr "sha1" "$@";; + destroy) + shift; tpm1_destroy "$@";; seal) shift; tpm1_seal "$@";; startsession) @@ -716,6 +744,8 @@ case "$subcmd" in tpm2_counter_inc "$@";; counter_create) tpm2_counter_cre "$@";; + destroy) + tpm2_destroy "$@";; seal) tpm2_seal "$@";; startsession) diff --git a/initrd/bin/unpack_initramfs.sh b/initrd/bin/unpack_initramfs.sh new file mode 100755 index 000000000..8c1a5cd4e --- /dev/null +++ b/initrd/bin/unpack_initramfs.sh @@ -0,0 +1,110 @@ +#! /bin/bash +set -e -o pipefail + +. /etc/functions + +# Unpack a Linux initramfs archive. +# +# In general, the initramfs archive is one or more cpio archives, optionally +# compressed, concatenated together. Uncompressed and compressed segments can +# exist in the same file. Zero bytes between segments are skipped. To properly +# unpack such an archive, all segments must be unpacked. +# +# This script unpacks such an archive, but with a limitation that once a +# compressed segment is reached, no more segments can be read. This works for +# common initrds on x86, where the microcode must be stored in an initial +# uncompressed segment, followed by the "real" initramfs content which is +# usually in one compressed segment. +# +# The limitation comes from gunzip/unzstd, there's no way to prevent them from +# consuming trailing data or tell us the member/frame length. The script +# succeeds with whatever was extracted, since this is used to extract particular +# files and boot can proceed as long as those files were found. + +INITRAMFS_ARCHIVE="$1" +DEST_DIR="$2" +shift +shift +# rest of args go to cpio, can specify filename patterns +CPIO_ARGS=("$@") + +# Consume zero bytes, the first nonzero byte read (if any) is repeated on stdout +consume_zeros() { + next_byte='00' + while [ "$next_byte" = "00" ]; do + # if we reach EOF, next_byte becomes empty (dd does not fail) + next_byte="$(dd bs=1 count=1 status=none | xxd -p | tr -d ' ')" + done + # if we finished due to nonzero byte (not EOF), then carry that byte + if [ -n "$next_byte" ]; then + echo -n "$next_byte" | xxd -p -r + fi +} + +unpack_cpio() { + (cd "$dest_dir"; cpio -i "${CPIO_ARGS[@]}" 2>/dev/null) +} + +# unpack the first segment of an archive, then write the rest to another file +unpack_first_segment() { + unpack_archive="$1" + dest_dir="$2" + rest_archive="$3" + + mkdir -p "$dest_dir" + + # peek the beginning of the file to determine what type of content is next + magic="$(dd if="$unpack_archive" bs=6 count=1 status=none | xxd -p)" + + # read this segment of the archive, then write the rest to the next file + ( + # Magic values correspond to Linux init/initramfs.c (zero, cpio) and + # lib/decompress.c (gzip) + case "$magic" in + 00*) + # Skip zero bytes and copy the first nonzero byte + consume_zeros + # Copy the remaining data + cat + ;; + 303730373031*|303730373032*) # plain cpio + # Unpack the plain cpio, this stops reading after the trailer + unpack_cpio + # Copy the remaining data + cat + ;; + 1f8b*|1f9e*) # gzip + # gunzip won't stop when reaching the end of the gzipped member, + # so we can't read another segment after this. We can't + # reasonably determine the member length either, this requires + # walking all the compressed blocks. + gunzip | unpack_cpio + ;; + 28b5*) # zstd + # Like gunzip, this will not stop when reaching the end of the + # frame, and determining the frame length requires walking all + # of its blocks. + (zstd-decompress -d || true) | unpack_cpio + ;; + *) # unknown + die "Can't decompress initramfs archive, unknown type: $magic" + ;; + esac + ) <"$unpack_archive" >"$rest_archive" + + orig_size="$(stat -c %s "$unpack_archive")" + rest_size="$(stat -c %s "$rest_archive")" + DEBUG "archive segment $magic: $((orig_size - rest_size)) bytes" +} + +DEBUG "Unpacking $INITRAMFS_ARCHIVE to $DEST_DIR" + +next_archive="$INITRAMFS_ARCHIVE" +rest_archive="/tmp/unpack_initramfs_rest" + +# Break when there is no remaining data +while [ -s "$next_archive" ]; do + unpack_first_segment "$next_archive" "$DEST_DIR" "$rest_archive" + next_archive="/tmp/unpack_initramfs_next" + mv "$rest_archive" "$next_archive" +done diff --git a/initrd/bin/unseal-hotp b/initrd/bin/unseal-hotp index 731746172..9cdc263da 100755 --- a/initrd/bin/unseal-hotp +++ b/initrd/bin/unseal-hotp @@ -40,8 +40,14 @@ fi if [ "$CONFIG_TPM" = "y" ]; then DEBUG "Unsealing HOTP secret reuses TOTP sealed secret..." tpmr unseal 4d47 0,1,2,3,4,7 312 "$HOTP_SECRET" +else + # without a TPM, generate a secret based on the SHA-256 of the ROM + secret_from_rom_hash > "$HOTP_SECRET" || die "Reading ROM failed" fi +# Truncate the secret if it is longer than the maximum HOTP secret +truncate_max_bytes 20 "$HOTP_SECRET" + if ! hotp $counter_value < "$HOTP_SECRET"; then shred -n 10 -z -u "$HOTP_SECRET" 2> /dev/null die 'Unable to compute HOTP hash?' diff --git a/initrd/bin/usb-autoboot.sh b/initrd/bin/usb-autoboot.sh new file mode 100755 index 000000000..af7a0ac06 --- /dev/null +++ b/initrd/bin/usb-autoboot.sh @@ -0,0 +1,53 @@ +#!/bin/bash +set -o pipefail + +. /etc/functions +. /etc/gui_functions + +# Automatically boot to a bootable USB medium if present. This is for +# unattended boot; there is no UI. +# There are three possible results: +# * Automatic boot occurs - script does not return (kexec happens) +# * User interrupted automatic boot - script returns 0. Skip normal boot and go +# to the boot menu (don't prompt for two automatic boots). +# * No automatic boot was attempted - script returns nonzero. Continue with +# normal automatic boot. + +# These may die for failure, nonzero exit is correct (USB boot wasn't possible) +enable_usb +enable_usb_storage + +mkdir -p /media + +parse_boot_options() +{ + BOOTDIR="$1" + for i in $(find "$BOOTDIR" -name '*.cfg'); do + kexec-parse-boot "$BOOTDIR" "$i" + done +} + +# Look for any bootable USB medium. +list_usb_storage >/tmp/usb-autoboot-usb-storage +while read -u 4 -r USB_BLOCK_DEVICE; do + mount "$USB_BLOCK_DEVICE" /media || continue + USB_DEFAULT_BOOT="$(parse_boot_options /media | head -1)" + if [ -n "$USB_DEFAULT_BOOT" ]; then + # Boot automatically, unless the user interrupts. + echo -e "\n\n" + echo "Found bootable USB: $(echo "$USB_DEFAULT_BOOT" | cut -d '|' -f 1)" + if ! pause_automatic_boot; then + # User interrupted, go to boot menu + umount /media + exit 0 + fi + echo -e "\n\nBooting from USB...\n\n" + kexec-boot -b /media -e "$USB_DEFAULT_BOOT" + # If kexec-boot returned, the boot obviously did not occur, + # return nonzero below so the normal OS boot will continue. + fi + umount /media +done 4&2 "Restricted Boot enabled, recovery console disabled, rebooting in 5 seconds" + sleep 5 + /bin/reboot + fi while [ true ] do echo >&2 "!!!!! Starting recovery shell" diff --git a/initrd/etc/distro/keys/pureos.key b/initrd/etc/distro/keys/pureos.key new file mode 100644 index 000000000..bf34dc827 --- /dev/null +++ b/initrd/etc/distro/keys/pureos.key @@ -0,0 +1,51 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBFfD+ecBEADr5q0IAJ/8wBjX/GIVKrA19R0qaCKBjWvoWqT7EeJp0Oj9bHO7 +sTKqXvzpRZajqW4Ad1O3b4ht9rVrzLMgbc/RGK26LEFEqAb1DqZQfMXwKhdi6Hu+ +TeVbNqTUmOoisouwjKqT+f6NofKOwxukBqoZcnxu4e3t4xCQ97vFU80MIhx8tXro +HIyw3dQjsQvoajBMeshdx8Sfp/h2r7PUbugtn1vacLDF/JnKgBEmmoCdBzKyUygk +8okBs+L57MMDSwaSh5WmGMp5xXW+iahCfVEIWIVAlTOPm+jBMUkpkaQRf004fIT4 +WhIyvT5g6lc8aljBFqmTIPGCQDSLyzOG1LwsvEgDVWGg69oNYuqSNibZeN0ko5YU +X8V9IGNAZwmTVUwCJw58nK4lk8r5EvohjSIglFjhrbTZXyPuBb627gT0GSqHjrMH +qGTPe2wtf+OMSvPD27HNFQHeq54zBwQLwBdrSScO9QqIRat22UZDWt8O6pubZ6Fr +ay3ioYOqx/WnaA4nyhZv53ShXUNMmi7MuOpppqPzPgPgLbu1zeVcCM5DWJj7Q/9r +uRGrd1+6Gk2iVyTj1R+I4o4OznNQNB9mcVIVQKlo9S29YeLA5UAblZRW0lBpyEdB +0qnKka2hglH6kqDoewzOAER2zusBtnPGp3qvHu/u4JstGBCYiBwTfro+UwARAQAB +tEVQdXJpc20gUHVyZU9TIEFyY2hpdmUgKFB1cmVPUyBBcmNoaXZlIFNpZ25pbmcg +S2V5KSA8c3lzYWRtaW5AcHVyaS5zbT6JAjgEEwECACIFAlfi/n4CGwMGCwkIBwMC +BhUIAgkKCwQWAgMBAh4BAheAAAoJECtKU/K0HOByjx8P/13V3Ia7DK9MonFeXiY5 +BNFzF9lpgePAl4y8M1pbOHL+pD90N4KIV+uFvIXRympx3G/Y+lH3NhxapIfJcNHI +pue9Kziz8Py6oqCNbv2qlomMu8sXHOuJ6niuNa4yDqGNfPuJqVt5cTvsTfzKHG8H +lgD0f3H1+aj0WZofqgWxgAaIRf3G3f2NxPh9ng07OAKxDyBdYdTSrksUEhwSUCHI +KWW9YV8WfjEt1yznEHqfROJFJ8M+36z18uaG5bl2RdLo0x3Bm3utgXPiCkE9zW3V +eGEqw471kktAYd0rMEqGJpO1ifz6Y6eSfQLEVpho+mxI+QGE/E8DY2i0phxh+XN0 +UMd+xVR1VSEGF2VHeu3YTADBLZsYozzw5+BNnXkJy3lvrZiob2fUBBUZg5/yJCXE +/gAFAuWseQQe7N7qMdPMq8xViAs5NGs2lBffUPnH6BjWAhmLxiW4p2ptLza5BCli +bnFodlS4v737EvgH9cyctUBrrOy/totcJeMZ20Lxa+e2bsTUwW4SraLKUoAArcXf +Qtysh6TPTHMMZvbM9d9fqdNv834y0C7Eh6n/Ar3EdlurvRAL+gW/1XhZEdNj5yfY +V3FSSdXH3YN9AsStxxZfzyghAU/tYvPqslceSe/ooqCM1TrWD2dFzrCJiraM0LNf +65pPjODRzIxff0fXYj+z6UD9uQINBFfD+ecBEADHqYuw0BjUknJyIoP9dfWp1j2D +QhwjTLtYPvz7C77KlJ+cl56XyQJEqpuhQkVJ9GAX492UOLnZqvty3cDzL6JTcEdI +GoMrMvM+l2r2HMS/Ws3arduCbPQls8Ub+xacfAAz7a+amCgqSgl9UW3teaKEQYeJ +yGCLpnclWU4sF4PkNLQtLp7cibdYy34OGjHqQBSImeWP1N/tIU2GOsOSftuUBKtR +T/uVn0xUkegCy1m15o5TaGo09SvHlaYE92VU/P/SEDKn+CfC+eYqy34vRrcsQ6fn +0va64XYvYk+lFu9N770JtAnB7bM++xSCYdbXFgOtPDjjBYtj3yypGFDGmBSoE2nX +JmRCwzWldb4KRJKK1auvK+OE78hkJQcx9NgdGyrj81OqAdsurjtYDz/mF0/n/oCn +U/2n0orGzh5+PbjyIFjrwYtDzkqnibh4FBngi90PDOFrBsXkuP16oyVkQXPivJFV +W61lFPQXKfCCyuRjMAjB2dgw2PYGPFSiVAgA8lvzHnBeFobGheepzeQi7+YALwOl +ve+4qLWx8nfB507LPSNkK6vX2lZWWdZbdJfsKEBLZm2mHo59Hn7RBJxIV+2x4jR8 +3KnCYNpMx6Fbw0BUmO+v1hD97MvBBSTU9vCEiPfC226ljJGy7bBK7PVu2VjlsWeF +8TxEaqEJJWwb4hwB/QARAQABiQIfBBgBAgAJBQJXw/nnAhsMAAoJECtKU/K0HOBy +cgAP/RlP9RxSRlX8pHNYrbRwgdIsG270fc+EosLQziGjf1At64Te26ovfAzq3nfS +MfDkLozEQx4lwmlKoGj1XksklUd/1vcZ1MUWfpHA313nv+/pe3e8uBeCKZVxhI+g +NW3WJ0dwgkbtf52ACyJaCbSk29zuDaD3E7/Pv9gzuXXCrd+oZdXK4oWv3eQVMrzk +bVBHnY8G7Os40LlJNPldtlg7BW6VWTNFZ2l6fK/xVft1ZpJEzfjkSmC8UB7tcDVa +UBwNvP/pJ7DiY0iTaT8XHE830BUhwuHG7M/+VEMZu92vrdKJAanjHiU/J5DRqaDf +tGxqDRZauYUHglikmGx77jkm8yqvomXNrdFLCA4Ow5dCazx0uHsZRdByU+wIG6aF +A9aYnBs73RPOQK2ktN3OsUsmmxYeY6X5iEHCxuKksdbzw1SLkblYh07YZQpfhof6 +SXMa9BKEvGhc6N7c4UAUTAnMs3vyBW/jH1GJXMiQHoDiNbhAZX0z9k3RXz6NIAYU +NDP9qgilojBaqK+5JqIuzViQGzL2DBGuIknBt8D5iOdgZNVuUSr7zwwHeJJhKtQu +3SrGX71QNc3juLoRCOCVDqMopEeqb4g3o1V3FyGtyrIge4TuxxtuN67gkcmNvIHC +kLzFG4lNrRQeGTXnpkUbJ1jGgxXuxF59pRQnHggeYQmenEJR +=aliF +-----END PGP PUBLIC KEY BLOCK----- diff --git a/initrd/etc/functions b/initrd/etc/functions index 9bb0e665b..5b1a719b0 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -81,6 +81,24 @@ confirm_totp() echo } +# Enable USB storage (if not already enabled), and wait for storage devices to +# be detected. If USB storage was already enabled, no wait occurs, this would +# have happened already when USB storage was enabled. +enable_usb_storage() +{ + if ! lsmod | grep -q usb_storage; then + timeout=0 + echo "Scanning for USB storage devices..." + insmod /lib/modules/usb-storage.ko >/dev/null 2>&1 \ + || die "usb_storage: module load failed" + while [[ $(list_usb_storage | wc -l) -eq 0 ]]; do + [[ $timeout -ge 8 ]] && break + sleep 1 + timeout=$(($timeout+1)) + done + fi +} + list_usb_storage() { TRACE "Under /etc/functions:list_usb_storage" @@ -248,7 +266,7 @@ check_config() { || die 'Failed to empty kexec tmp dir' fi - if [ ! -r $1/kexec.sig ]; then + if [ ! -r $1/kexec.sig -a "$CONFIG_BASIC" != "y" ]; then return fi @@ -267,6 +285,18 @@ check_config() { || die "Failed to copy kexec boot params to tmp" } +# Replace a file in a ROM (add it if the file does not exist) +replace_rom_file() { + ROM="$1" + ROM_FILE="$2" + NEW_FILE="$3" + + if (cbfs.sh -o "$ROM" -l | grep -q "$ROM_FILE") then + cbfs.sh -o "$ROM" -d "$ROM_FILE" + fi + cbfs.sh -o "$ROM" -a "$ROM_FILE" -f "$NEW_FILE" +} + replace_config() { TRACE "Under /etc/functions:replace_config" CONFIG_FILE=$1 @@ -284,6 +314,57 @@ replace_config() { rm -f ${CONFIG_FILE}.tmp } +# Set a config variable in a specific file to a given value - replace it if it +# exists, or add it. If added, the variable will be exported. +set_config() { + CONFIG_FILE="$1" + CONFIG_OPTION="$2" + NEW_SETTING="$3" + + if grep -q "$CONFIG_OPTION" "$CONFIG_FILE"; then + replace_config "$CONFIG_FILE" "$CONFIG_OPTION" "$NEW_SETTING" + else + echo "export $CONFIG_OPTION=\"$NEW_SETTING\"" >>"$CONFIG_FILE" + fi +} + +# Set a value in config.user, re-combine configs, and update configs in the +# environment. +set_user_config() { + CONFIG_OPTION="$1" + NEW_SETTING="$2" + + set_config /etc/config.user "$CONFIG_OPTION" "$NEW_SETTING" + combine_configs + . /tmp/config +} + +# Load a config value to a variable, defaulting to empty. Does not fail if the +# config is not set (since it would expand to empty by default). +load_config_value() +{ + local config_name="$1" + if grep -q "$config_name=" /tmp/config; then + grep "$config_name=" /tmp/config | tail -n1 | cut -f2 -d '=' | tr -d '"' + fi +} + +# Generate a secret for TPM-less HOTP by reading the ROM. Output is the +# sha256sum of the ROM (binary, not printable), which can be truncated to the +# supported secret length. +secret_from_rom_hash() { + local ROM_IMAGE="/tmp/coreboot-notpm.rom" + + echo -e "\nTPM not detected; measuring ROM directly\n" 1>&2 + + # Read the ROM if we haven't read it yet + if [ ! -f "${ROM_IMAGE}" ]; then + flash.sh -r "${ROM_IMAGE}" >/dev/null 2>&1 || return 1 + fi + + sha256sum "${ROM_IMAGE}" | cut -f1 -d ' ' | fromhex_plain +} + update_checksums() { TRACE "Under /etc/functions:update_checksums" @@ -484,11 +565,58 @@ detect_boot_device() return 1 } +scan_boot_options() +{ + local bootdir config option_file + bootdir="$1" + config="$2" + option_file="$3" + + if [ -r $option_file ]; then rm $option_file; fi + for i in `find $bootdir -name "$config"`; do + DO_WITH_DEBUG kexec-parse-boot "$bootdir" "$i" >> $option_file + done + # FC29/30+ may use BLS format grub config files + # https://fedoraproject.org/wiki/Changes/BootLoaderSpecByDefault + # only parse these if $option_file is still empty + if [ ! -s $option_file ] && [ -d "$bootdir/loader/entries" ]; then + for i in `find $bootdir -name "$config"`; do + kexec-parse-bls "$bootdir" "$i" "$bootdir/loader/entries" >> $option_file + done + fi +} + calc() { awk "BEGIN { print "$*" }"; } +# truncate a file to a size only if it is longer (busybox truncate lacks '<' and +# always sets the file size) +truncate_max_bytes() { + local bytes="$1" + local file="$2" + if [ "$(stat -c %s "$file")" -gt "$bytes" ]; then + truncate -s "$bytes" "$file" + fi +} + +# Busybox xxd -p pads the last line with spaces to 60 columns, which not only +# trips up many scripts, it's very difficult to diagnose by looking at the +# output. Delete line breaks and spaces to really get plain hex output. +tohex_plain() { + xxd -p | tr -d '\n ' +} + +# Busybox xxd -p -r silently truncates lines longer than 60 hex chars. +# Shorter lines are OK, spaces are OK, and even splitting a byte across lines is +# allowed, so just fold the text to maximum 60 column lines. +# Note that also unlike GNU xxd, non-hex chars in input corrupt the output (GNU +# xxd ignores them). +fromhex_plain() { + fold -w 60 | xxd -p -r +} + print_battery_health() { if [ -d /sys/class/power_supply/BAT* ]; then diff --git a/initrd/etc/gui_functions b/initrd/etc/gui_functions index d1920bd30..ac9fbcfbd 100755 --- a/initrd/etc/gui_functions +++ b/initrd/etc/gui_functions @@ -2,6 +2,17 @@ # Shell functions for common operations using fbwhiptail . /etc/functions +# Pause for the configured timeout before booting automatically. Returns 0 to +# continue with automatic boot, nonzero if user interrupted. +pause_automatic_boot() +{ + if IFS= read -t "$CONFIG_AUTO_BOOT_TIMEOUT" -s -n 1 -p \ + "Automatic boot in $CONFIG_AUTO_BOOT_TIMEOUT seconds unless interrupted by keypress... "; then + return 1 # Interrupt automatic boot + fi + return 0 # Continue with automatic boot +} + mount_usb() { TRACE "under gui_functions:mount_usb" @@ -13,11 +24,11 @@ mount_usb() mount-usb && USB_FAILED=0 || ( [ $? -eq 5 ] && exit 1 || USB_FAILED=1 ) if [ $USB_FAILED -ne 0 ]; then whiptail $BG_COLOR_ERROR --title 'USB Drive Missing' \ - --msgbox "Insert your USB drive and press Enter to continue." 16 60 + --msgbox "Insert your USB drive and press Enter to continue." 0 80 mount-usb && USB_FAILED=0 || ( [ $? -eq 5 ] && exit 1 || USB_FAILED=1 ) if [ $USB_FAILED -ne 0 ]; then whiptail $BG_COLOR_ERROR --title 'ERROR: Mounting /media Failed' \ - --msgbox "Unable to mount USB device" 16 60 + --msgbox "Unable to mount USB device" 0 80 exit 1 fi fi @@ -68,7 +79,45 @@ file_selector() fi else whiptail $BG_COLOR_ERROR --title 'ERROR: No Files Found' \ - --msgbox "No Files found matching the pattern. Aborting." 16 60 + --msgbox "No Files found matching the pattern. Aborting." 0 80 exit 1 fi } + +show_system_info() +{ + TRACE "Under /bin/gui-init:show_system_info" + battery_charge="$(print_battery_charge)" + battery_health="$(print_battery_health)" + if [ -n $battery_charge -a -n $battery_health ];then + battery_status="\nBattery charge: $battery_charge%\nBattery health: $battery_health%\n" + fi + + memtotal=$(cat /proc/meminfo | grep 'MemTotal' | tr -s ' ' | cut -f2 -d ' ') + memtotal=$((${memtotal} / 1024 / 1024 + 1)) + cpustr=$(cat /proc/cpuinfo | grep 'model name' | uniq | sed -r 's/\(R\)//;s/\(TM\)//;s/CPU //;s/model name.*: //') + kernel=$(uname -s -r) + + whiptail $BG_COLOR_MAIN_MENU --title 'System Info' \ + --msgbox "${BOARD_NAME}\n\nFW_VER: ${FW_VER}\nKernel: ${kernel}\n\nCPU: ${cpustr}\nRAM: ${memtotal} GB\n$battery_status\n$(fdisk -l | grep -e '/dev/sd.:' -e '/dev/nvme.*:' | sed 's/B,.*/B/')" 0 80 +} + +# Get "Enable" or "Disable" to display in the configuration menu, based on a +# setting value +get_config_display_action() +{ + [ "$1" = "y" ] && echo "Disable" || echo "Enable" +} + +# Invert a config value +invert_config() +{ + [ "$1" = "y" ] && echo "n" || echo "y" +} + +# Get "Enable" or "Disable" for a config that internally is inverted (because it +# disables a behavior that is on by default). +get_inverted_config_display_action() +{ + get_config_display_action "$(invert_config "$1")" +} diff --git a/initrd/init b/initrd/init index a92557450..7fd9c612a 100755 --- a/initrd/init +++ b/initrd/init @@ -59,7 +59,6 @@ TRACE "Under init" if [ ! -e /dev/tpm0 ]; then CONFIG_TPM='n' CONFIG_TPM2_TOOLS='n' - warn 'No TPM found...' fi #Specify whiptail background colors cues under FBWhiptail only @@ -88,6 +87,28 @@ export GPG_TTY=/dev/console [ -x /bin/bash ] && /bin/key-init +# Override CONFIG_USE_BLOB_JAIL if needed and persist via user config +if lspci -n | grep -q "8086:2723"; then + if ! cat /etc/config.user 2>/dev/null | grep -q "USE_BLOB_JAIL"; then + echo "CONFIG_USE_BLOB_JAIL=y" >> /etc/config.user + fi +fi + +# Override CONFIG_TPM and CONFIG_TPM2_TOOLS from /etc/config with runtime value +# determined above. +# +# Values in user config have higher priority during combining thus effectively +# changing the value for the rest of the scripts which source /tmp/config. +echo "export CONFIG_TPM=\"$CONFIG_TPM\"" >> /etc/config.user +echo "export CONFIG_TPM2_TOOLS=\"$CONFIG_TPM2_TOOLS\"" >> /etc/config.user + +# CONFIG_BASIC was previously CONFIG_PUREBOOT_BASIC in the PureBoot distribution. +# Substitute it in config.user if present for backward compatibility. +sed -i -e 's/^export CONFIG_PUREBOOT_BASIC=/export CONFIG_BASIC=/g' /etc/config.user + +combine_configs +. /tmp/config + # Setup recovery serial shell if [ ! -z "$CONFIG_BOOT_RECOVERY_SERIAL" ]; then stty -F "$CONFIG_BOOT_RECOVERY_SERIAL" 115200 @@ -114,23 +135,12 @@ if [ "$boot_option" = "r" ]; then # Start an interactive shell recovery 'User requested recovery shell' # just in case... - if [ "$CONFIG_TPM" = "y" ]; then - tpmr extend -ix 4 -ic recovery - fi - exec /bin/sh exit fi -# Override CONFIG_TPM and CONFIG_TPM2_TOOLS from /etc/config with runtime value -# determined above. -# -# Values in user config have higher priority during combining thus effectively -# changing the value for the rest of the scripts which source /tmp/config. -echo "export CONFIG_TPM=\"$CONFIG_TPM\"" >> /etc/config.user -echo "export CONFIG_TPM2_TOOLS=\"$CONFIG_TPM2_TOOLS\"" >> /etc/config.user - -combine_configs -. /tmp/config +if [ "$CONFIG_BASIC" = "y" ]; then + echo -e "***** BASIC mode: tamper detection disabled\n" > /dev/tty0 +fi # export firmware version export FW_VER=$(dmesg | grep 'DMI' | grep -o 'BIOS.*' | cut -f2- -d ' ') @@ -143,6 +153,16 @@ if [ ! -z "$CONFIG_BOOT_DEV" ]; then echo >> /etc/fstab "$CONFIG_BOOT_DEV /boot auto defaults,ro 0 0" fi +if [ "$CONFIG_BASIC" = "y" ]; then + CONFIG_BOOTSCRIPT=/bin/gui-init-basic + export CONFIG_HOTPKEY=n +fi + +# Perform board-specific init if present +if [ -x /bin/board-init.sh ]; then + /bin/board-init.sh +fi + if [ ! -x "$CONFIG_BOOTSCRIPT" -a ! -x "$CONFIG_BOOTSCRIPT_NETWORK" ]; then recovery 'Boot script missing? Entering recovery shell' else @@ -163,17 +183,11 @@ else fi exec "$CONFIG_BOOTSCRIPT" - - # We should never reach here, but just in case... - recovery 'Boot script failure? Entering recovery shell' else # wait for boot via network to occur pause_recovery 'Override network boot. Entering recovery shell' fi fi -# belts and suspenders, just in case... -if [ "$CONFIG_TPM" = "y" ]; then - tpmr extend -ix 4 -ic recovery -fi -exec /bin/sh +# We should never reach here, but just in case... +recovery 'Boot script failure? Entering recovery shell' diff --git a/modules/coreboot b/modules/coreboot index 2f80f5803..43e69d3ea 100644 --- a/modules/coreboot +++ b/modules/coreboot @@ -47,6 +47,11 @@ else ifeq "$(CONFIG_COREBOOT_VERSION)" "talos_2" coreboot_commit_hash = c8aed443c631042ad2b0326c35cd0b774752b924 coreboot_repo := https://github.com/Dasharo/coreboot +else ifeq "$(CONFIG_COREBOOT_VERSION)" "purism" + coreboot_version := git + coreboot_repo := https://source.puri.sm/coreboot/coreboot + coreboot_commit_hash := a899f08d2789db1dd9b02cff34179c4d38e6d0e3 + EXTRA_FLAGS := -fdebug-prefix-map=$(pwd)=heads -gno-record-gcc-switches -Wno-error=packed-not-aligned -Wno-error=address-of-packed-member else $(error "$(BOARD): does not specify coreboot version under CONFIG_COREBOOT_VERSION") endif @@ -70,7 +75,7 @@ EXTRA_FLAGS ?= -fdebug-prefix-map=$(pwd)=heads -gno-record-gcc-switches -Wno-err coreboot_configure := \ mkdir -p "$(build)/$(coreboot_dir)" \ && $(call install_config,$(pwd)/$(CONFIG_COREBOOT_CONFIG),$(build)/$(coreboot_dir)/.config) \ - && echo 'CONFIG_LOCALVERSION="Heads-$(HEADS_GIT_VERSION)"' >> $(build)/$(coreboot_dir)/.config \ + && echo 'CONFIG_LOCALVERSION="$(BRAND_NAME)-$(HEADS_GIT_VERSION)"' >> $(build)/$(coreboot_dir)/.config \ && echo 'CONFIG_MAINBOARD_SMBIOS_PRODUCT_NAME="$(BOARD)"' >> $(build)/$(coreboot_dir)/.config \ && $(MAKE) olddefconfig \ -C "$(build)/$(coreboot_base_dir)" \ diff --git a/modules/fbwhiptail b/modules/fbwhiptail index 9e6f63218..879354de0 100644 --- a/modules/fbwhiptail +++ b/modules/fbwhiptail @@ -2,11 +2,11 @@ modules-$(CONFIG_FBWHIPTAIL) += fbwhiptail fbwhiptail_depends := cairo $(musl_dep) -fbwhiptail_version := 1.0 +fbwhiptail_version := 99fe815fb35d7650873aa413a3024ef1496fe4a3 fbwhiptail_dir := fbwhiptail-$(fbwhiptail_version) fbwhiptail_tar := fbwhiptail-$(fbwhiptail_version).tar.gz fbwhiptail_url := https://source.puri.sm/firmware/fbwhiptail/-/archive/$(fbwhiptail_version)/fbwhiptail-$(fbwhiptail_version).tar.gz -fbwhiptail_hash := de4fe774b48fd2d1ce10ad2d44cb2d9f4a52bcaac37da83d9d05248d2428c5e3 +fbwhiptail_hash := bd210b52b0916eb081219a312a6fa1b3acd8582ca6198a196e232f8aa55bbce9 fbwhiptail_target := \ $(MAKE_JOBS) \ diff --git a/modules/ioport b/modules/ioport new file mode 100644 index 000000000..9d59fb708 --- /dev/null +++ b/modules/ioport @@ -0,0 +1,22 @@ +modules-$(CONFIG_IOPORT) += ioport + +ioport_version := 1.2 +ioport_dir := ioport-$(ioport_version) +ioport_tar := ioport-$(ioport_version).tar.gz +ioport_url := https://people.redhat.com/rjones/ioport/files/$(ioport_tar) +ioport_hash := 7fac1c4b61eb9411275de0e1e7d7a8c3f34166f64f16413f50741e8fce2b8dc0 + +ioport_configure := CFLAGS=-Os ./configure \ + $(CROSS_TOOLS) \ + --prefix "/" \ + --host i386-elf-linux + +ioport_target := \ + $(MAKE_JOBS) $(CROSS_TOOLS) inb && \ + $(MAKE) -C "$(build)/$(ioport_dir)" all-local + +ioport_output := \ + inb \ + outb + +ioport_depends := $(musl_dep) diff --git a/modules/linux b/modules/linux index dbf709915..afcabf4e5 100644 --- a/modules/linux +++ b/modules/linux @@ -31,6 +31,9 @@ linux_hash := a6fbd4ee903c128367892c2393ee0d9657b6ed3ea90016d4dc6f1f6da20b2330 else ifeq "$(CONFIG_LINUX_VERSION)" "5.10.5" linux_version := 5.10.5 linux_hash := 3991a9e16a187d78d5f414d89236ae5d7f404a69e60c4c42a9d262ee19612ef4 +else ifeq "$(CONFIG_LINUX_VERSION)" "6.1.8" +linux_version := 6.1.8 +linux_hash := b60bb53ab8ba370a270454b11e93d41af29126fc72bd6ede517673e2e57b816d else $(error "$(BOARD): does not specify linux kernel version under CONFIG_LINUX_VERSION") endif diff --git a/modules/purism-blobs b/modules/purism-blobs index ef3c3c712..e75c6bd11 100644 --- a/modules/purism-blobs +++ b/modules/purism-blobs @@ -1,11 +1,11 @@ modules-$(CONFIG_PURISM_BLOBS) += purism-blobs purism-blobs_base_dir := coreboot-$(CONFIG_COREBOOT_VERSION)/3rdparty/purism-blobs -purism-blobs_version := 51227164fe693042b66c7372f54057d8082dff08 +purism-blobs_version := 995f66c445841b86e6596e9b297cc4888c0257e5 purism-blobs_tar := purism-blobs-${purism-blobs_version}.tar.gz purism-blobs_tar_opt := --strip 1 purism-blobs_url := https://source.puri.sm/coreboot/purism-blobs/-/archive/${purism-blobs_version}/${purism-blobs_tar} -purism-blobs_hash := 4e0eb2010631fb96fff4b58cf03a47c554e5524a2cd6b4d3809fd3d0985ebb6e +purism-blobs_hash := 6d26c129fe8d719a49f4f726383baaf7edb6131183bada4167711b5a5312f516 ## there is nothing to be built purism-blobs_output := .built diff --git a/modules/zstd b/modules/zstd new file mode 100644 index 000000000..3d7bd4b36 --- /dev/null +++ b/modules/zstd @@ -0,0 +1,20 @@ +modules-$(CONFIG_ZSTD) += zstd + +zstd_version := 1.5.5 +zstd_dir := zstd-$(zstd_version) +zstd_tar := zstd-$(zstd_version).tar.gz +zstd_url := https://github.com/facebook/zstd/releases/download/v$(zstd_version)/$(zstd_tar) +zstd_hash := 9c4396cc829cfae319a6e2615202e82aad41372073482fce286fac78646d3ee4 + +zstd_configure := true + +# Only the decompressor is built and installed, to be able to read zstd-compressed +# initramfs archives. +zstd_target := \ + $(MAKE_JOBS) $(CROSS_TOOLS) -C programs CFLAGS="-g0 -Os" \ + HAVE_ZLIB=0 \ + HAVE_LZMA=0 \ + HAVE_LZ4=0 \ + zstd-decompress + +zstd_output := programs/zstd-decompress diff --git a/patches/linux-6.1.8/0001-fake-acpi.patch b/patches/linux-6.1.8/0001-fake-acpi.patch new file mode 100644 index 000000000..0c8b3b546 --- /dev/null +++ b/patches/linux-6.1.8/0001-fake-acpi.patch @@ -0,0 +1,32 @@ +diff --recursive -u ./clean/linux-4.9.80/drivers/acpi/acpica/evxfevnt.c linux-4.9.80/drivers/acpi/acpica/evxfevnt.c +--- ./clean/linux-4.9.80/drivers/acpi/acpica/evxfevnt.c 2018-02-03 11:05:43.000000000 -0500 ++++ linux-4.9.80/drivers/acpi/acpica/evxfevnt.c 2018-02-07 15:51:28.786502597 -0500 +@@ -111,6 +111,8 @@ + } + + ACPI_ERROR((AE_INFO, "Hardware did not enter ACPI mode")); ++printk("%s:%d faking ACPI mode\n", __func__, __LINE__); ++ return_ACPI_STATUS(AE_OK); + return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); + } + +diff --recursive -u ./clean/linux-4.9.80/drivers/acpi/acpica/hwacpi.c linux-4.9.80/drivers/acpi/acpica/hwacpi.c +--- ./clean/linux-4.9.80/drivers/acpi/acpica/hwacpi.c 2018-02-03 11:05:43.000000000 -0500 ++++ linux-4.9.80/drivers/acpi/acpica/hwacpi.c 2018-02-07 15:51:35.126557868 -0500 +@@ -168,12 +168,16 @@ + + status = acpi_read_bit_register(ACPI_BITREG_SCI_ENABLE, &value); + if (ACPI_FAILURE(status)) { ++printk("%s:%d faking ACPI mode\n", __func__, __LINE__); ++ return_UINT32(ACPI_SYS_MODE_ACPI); + return_UINT32(ACPI_SYS_MODE_LEGACY); + } + + if (value) { + return_UINT32(ACPI_SYS_MODE_ACPI); + } else { ++//printk("%s:%d faking ACPI mode\n", __func__, __LINE__); ++// return_UINT32(ACPI_SYS_MODE_ACPI); + return_UINT32(ACPI_SYS_MODE_LEGACY); + } + } diff --git a/patches/linux-6.1.8/0002-nmi-squelch.patch b/patches/linux-6.1.8/0002-nmi-squelch.patch new file mode 100644 index 000000000..bce1cd2f0 --- /dev/null +++ b/patches/linux-6.1.8/0002-nmi-squelch.patch @@ -0,0 +1,20 @@ +diff --recursive -u ./clean/linux-4.9.80/arch/x86/kernel/nmi.c linux-4.9.80/arch/x86/kernel/nmi.c +--- ./clean/linux-4.9.80/arch/x86/kernel/nmi.c 2018-02-03 11:05:43.000000000 -0500 ++++ linux-4.9.80/arch/x86/kernel/nmi.c 2018-02-07 18:56:10.475613884 -0500 +@@ -303,6 +303,8 @@ + + __this_cpu_add(nmi_stats.unknown, 1); + ++#if 0 ++// qemu generates these for some reason + pr_emerg("Uhhuh. NMI received for unknown reason %02x on CPU %d.\n", + reason, smp_processor_id()); + +@@ -311,6 +313,7 @@ + nmi_panic(regs, "NMI: Not continuing"); + + pr_emerg("Dazed and confused, but trying to continue\n"); ++#endif + } + NOKPROBE_SYMBOL(unknown_nmi_error); + diff --git a/patches/linux-6.1.8/0010-winterfell-ahci.patch b/patches/linux-6.1.8/0010-winterfell-ahci.patch new file mode 100644 index 000000000..7f2417736 --- /dev/null +++ b/patches/linux-6.1.8/0010-winterfell-ahci.patch @@ -0,0 +1,18 @@ +diff --recursive -u ./clean/linux-4.9.80/drivers/ata/libahci.c linux-4.9.80/drivers/ata/libahci.c +--- ./clean/linux-4.9.80/drivers/ata/libahci.c 2018-02-03 11:05:43.000000000 -0500 ++++ linux-4.9.80/drivers/ata/libahci.c 2018-02-07 18:02:32.526535910 -0500 +@@ -537,8 +537,12 @@ + } + + /* fabricate port_map from cap.nr_ports for < AHCI 1.3 */ +- if (!port_map && vers < 0x10300) { +- port_map = (1 << ahci_nr_ports(cap)) - 1; ++ if (!port_map) { // && vers < 0x10300) { ++ printk("%s: saved_port=%02x\n", __func__, hpriv->saved_port_map); ++ writel(0x1, mmio + HOST_PORTS_IMPL); ++ port_map = readl(mmio + HOST_PORTS_IMPL); ++ ++ //port_map = (1 << ahci_nr_ports(cap)) - 1; + dev_warn(dev, "forcing PORTS_IMPL to 0x%lx\n", port_map); + + /* write the fixed up value to the PI register */