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/config/busybox.config b/config/busybox.config index 23c8fd3fd..5a03c3a38 100644 --- a/config/busybox.config +++ b/config/busybox.config @@ -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 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..017993a52 100644 --- a/config/linux-librem_common.config +++ b/config/linux-librem_common.config @@ -20,8 +20,7 @@ CONFIG_THREAD_INFO_IN_TASK=y # General setup # 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..3e3f238e7 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" 16 60 + 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 \ @@ -94,17 +139,9 @@ while true; do --msgbox "The /boot device was successfully changed to $SELECTED_FILE" 16 60 ;; "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 @@ -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,6 +172,8 @@ 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 @@ -153,6 +186,281 @@ while true; do exit 0 fi ;; + "R" ) + CURRENT_OPTION=`grep 'CONFIG_ROOT_DEV=' /tmp/config | tail -n1 | cut -f2 -d '=' | tr -d '"'` + 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.\n\nCurrently set to $CURRENT_OPTION." \ + "Root Device Selection" + if [ "$FILE" == "" ]; then + return + else + SELECTED_FILE=$FILE + fi + + replace_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" 16 60 + ;; + "D" ) + CURRENT_OPTION=`grep 'CONFIG_ROOT_DIRLIST=' /tmp/config | tail -n1 | cut -f2 -d '=' | tr -d '"'` + + echo "The current list of directories to hash is $CURRENT_OPTION" + echo -e "\nEnter the new list of directories separated by spaces, without any beginning forward slashes:" + echo -e "(Press enter with the list empty to cancel)" + read -r NEW_CONFIG_ROOT_DIRLIST + + # strip any leading forward slashes in case the user ignored us + NEW_CONFIG_ROOT_DIRLIST=$(echo $NEW_CONFIG_ROOT_DIRLIST | sed -e 's/^\///;s/ \// /g') + + #check if list empty + if [ -s $NEW_CONFIG_ROOT_DIRLIST ] ; then + whiptail --title 'Config change canceled' \ + --msgbox "Root device directory change canceled by user" 16 60 + break + fi + + replace_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" 16 60 + ;; + "B" ) + CURRENT_OPTION=`grep 'CONFIG_ROOT_CHECK_AT_BOOT=' /tmp/config | tail -n1 | cut -f2 -d '=' | tr -d '"'` + if [ "$CURRENT_OPTION" = "n" ]; then + if (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 + + replace_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." 16 60 + + 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 + + replace_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." 16 60 + 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." 16 60 + 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." 16 60 + + 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." 16 60 + fi + fi + ;; + "L" ) + if [ "$CONFIG_RESTRICTED_BOOT" != "y" ]; then + if (whiptail --title 'Enable Restricted Boot Mode?' \ + --yesno "This will disable booting from any unsigned files, + \nincluding kernels that have not yet been signed, + \n.isos without signatures, raw USB disks, + \nand will disable failsafe boot mode. + \n\nThis will also disable the recovery console. + \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." 16 60 + + fi + else + if (whiptail --title 'Disable Restricted Boot Mode?' \ + --yesno "This will allow booting from unsigned devices, + \nand will re-enable failsafe boot mode. + \n\nThis will also RESET the TPM and re-enable the recovery console. + \n\nProceeding will automatically update the boot firmware, reset TPM 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}" 16 60 + 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" 16 60 + /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." 16 60 + + 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." 16 60 + 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." 16 60 + 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." 16 60 + 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." 16 60 + 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." 16 60 + 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." 16 60 + 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." 16 60 + fi + fi + ;; esac done diff --git a/initrd/bin/flash-gui.sh b/initrd/bin/flash-gui.sh index e952272f5..b9bc4883c 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." 16 60 + exit 1 +fi + while true; do unset menu_choice whiptail $BG_COLOR_MAIN_MENU --title "Firmware Management Menu" \ diff --git a/initrd/bin/flash.sh b/initrd/bin/flash.sh index ca24fd106..33cf99ea5 100755 --- a/initrd/bin/flash.sh +++ b/initrd/bin/flash.sh @@ -14,7 +14,7 @@ TRACE "Under /bin/flash.sh" case "$CONFIG_FLASHROM_OPTIONS" in -* ) - echo "Board $CONFIG_BOARD detected, continuing..." + [ "$1" != "-s" ] && echo "Board $CONFIG_BOARD detected, continuing..." ;; * ) die "ERROR: No board has been configured!\n\nEach board requires specific flashrom options and it's unsafe to flash without them.\n\nAborting." @@ -125,6 +125,10 @@ flash_rom() { if [ "$READ" -eq 1 ]; then flashrom $CONFIG_FLASHROM_OPTIONS -r "${ROM}" \ || die "Backup to $ROM failed" + elif [ "$SHA" -eq 1 ]; then + flashrom $CONFIG_FLASHROM_OPTIONS -r "${ROM}" 1&>2 >/dev/null \ + || die "$ROM: Read failed" + sha256sum ${ROM} | cut -f1 -d ' ' else cp "$ROM" /tmp/${CONFIG_BOARD}.rom sha256sum /tmp/${CONFIG_BOARD}.rom @@ -157,20 +161,29 @@ flash_rom() { if [ "$1" == "-c" ]; then CLEAN=1 READ=0 + SHA=0 ROM="$2" elif [ "$1" == "-r" ]; then CLEAN=0 READ=1 + SHA=0 + ROM="$2" + touch $ROM +elif [ "$1" == "-s" ]; then + CLEAN=0 + READ=0 + SHA=1 ROM="$2" touch $ROM else CLEAN=0 READ=0 + SHA=0 ROM="$1" fi if [ ! -e "$ROM" ]; then - die "Usage: $0 [-c|-r] " + die "Usage: $0 [-c|-r|-s] " fi if [ "$READ" -eq 0 ] && [ "${ROM##*.}" = tgz ]; then diff --git a/initrd/bin/gui-init b/initrd/bin/gui-init index ec4ebe13e..6bf3d50e0 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 @@ -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" @@ -190,7 +198,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 @@ -263,6 +271,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() @@ -304,7 +337,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' \ @@ -334,18 +367,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() @@ -384,7 +410,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 -->' \ @@ -393,8 +419,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" @@ -422,14 +449,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" ;; @@ -553,24 +583,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" @@ -601,6 +613,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" 16 60 + 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 de59db6ef..66f649ce6 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..ab290c098 100755 --- a/initrd/bin/kexec-save-default +++ b/initrd/bin/kexec-save-default @@ -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..20da8d514 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" 16 60 + 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 @@ -251,19 +257,20 @@ default_select() { 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,6 +321,11 @@ user_select() { do_boot() { + if [ "$CONFIG_BASIC" != "y" ]; then + kexec-boot -b "$bootdir" -e "$option" -a "$add" -r "$remove" \ + || die "!!! Failed to boot w/ options: $option" + fi + if [ "$CONFIG_BOOT_REQ_ROLLBACK" = "y" -a "$valid_rollback" = "n" ]; then die "!!! Missing required rollback counter state" fi @@ -342,7 +354,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 +372,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 +393,7 @@ while true; do scan_options fi - if [ "$CONFIG_TPM" = "y" ]; then + if [ "$CONFIG_TPM" = "y" -a "$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..592aa5a46 100755 --- a/initrd/bin/media-scan +++ b/initrd/bin/media-scan @@ -92,6 +92,10 @@ if [ `cat /tmp/iso_menu.txt | wc -l` -gt 0 ]; then fi fi +if [ "$CONFIG_RESTRICTED_BOOT" = y ]; then + die "ISO boot failed in Restricted Boot mode." +fi + echo "!!! Could not find any ISO, trying bootable USB" # Attempt to pull verified config from device if [ -x /bin/whiptail ]; then diff --git a/initrd/bin/mount-usb b/initrd/bin/mount-usb index 70b1c0978..ea7abd3a7 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 diff --git a/initrd/bin/oem-factory-reset b/initrd/bin/oem-factory-reset index 639eb8610..01bff7026 100755 --- a/initrd/bin/oem-factory-reset +++ b/initrd/bin/oem-factory-reset @@ -392,146 +392,156 @@ 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" + + echo -e "\nEnter your Real Name (At least 5 characters long):" + read -r GPG_USER_NAME + while [[ ${#GPG_USER_NAME} -lt 5 ]]; do + { + echo -e "\nEnter your Real Name (At least 5 characters long):" + read -r GPG_USER_NAME + };done + + 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:" + 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 +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 -# 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:" - 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 - ## 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..4df24d393 --- /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" 16 60 + 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" 16 60 + 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" 16 60 + + 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" 16 60 + 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" 16 60 + 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" 16 60 + 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." 16 60 + + 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." 16 60 + 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" 16 60 + 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" 16 60 + fi + ;; + "u" ) + update_root_checksums + ;; + esac + +done +exit 0 diff --git a/initrd/bin/seal-hotpkey b/initrd/bin/seal-hotpkey index 7e8cc75b4..dae6fa9ab 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, use the first 20 characters of the ROM SHA256sum + secret_from_rom_hash > "$HOTP_SECRET" fi # Store counter in file instead of TPM for now, as it conflicts with Heads @@ -52,12 +62,12 @@ counter_value=1 enable_usb if ! hotp_verification info ; then - echo "Insert your $HOTPKEY_BRANDING and press Enter to configure it" + echo -e "\nInsert your $HOTPKEY_BRANDING and press Enter to configure it" read if ! 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 +80,29 @@ else HOTPKEY_BRANDING="HOTP USB Security Dongle" fi -echo -e "" -read -s -p "Enter your $HOTPKEY_BRANDING Admin PIN: " admin_pin -echo -e "\n" - -hotp_initialize "$admin_pin" $HOTP_SECRET $counter_value "$HOTPKEY_BRANDING" +# try using factory default admin PIN +admin_pin="12345678" +hotp_initialize "$admin_pin" $HOTP_SECRET $counter_value "$HOTPKEY_BRANDING" >/dev/null 2>&1 if [ $? -ne 0 ]; then + # prompt user for PIN and retry + echo "" + read -s -p "Enter your $HOTPKEY_BRANDING Admin PIN: " admin_pin 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 - 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 +118,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 c392d306a..da71a069b 100755 --- a/initrd/bin/tpmr +++ b/initrd/bin/tpmr @@ -250,6 +250,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 @@ -576,6 +602,8 @@ if [ "$CONFIG_TPM2_TOOLS" != "y" ]; then echo "$PCR_SIZE";; calcfuturepcr) shift; tpm1_calcfuturepcr "$@";; + destroy) + shift; tpm1_destroy "$@";; seal) shift; tpm1_seal "$@";; startsession) @@ -615,6 +643,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..470e3913f 100755 --- a/initrd/bin/unseal-hotp +++ b/initrd/bin/unseal-hotp @@ -40,6 +40,9 @@ 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, use the first 20 characters of the ROM SHA256sum + secret_from_rom_hash > "$HOTP_SECRET" fi if ! hotp $counter_value < "$HOTP_SECRET"; then 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..5b2123a6e 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,55 @@ 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 'n' +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 '"' + else + echo n + fi +} + +# Generate secret value using first 20 chars of ROM SHA256 hash +secret_from_rom_hash() { + local ROM_IMAGE="/tmp/coreboot-notpm.rom" + + echo -e "\nTPM not detected; measuring ROM directly\n" 1>&2 + # use a previously-copied image if it exists + if [ -f ${ROM_IMAGE} ]; then + sha256sum ${ROM_IMAGE} | cut -f1 -d ' ' | cut -c 1-20 | tr -d '\n' + else + flash.sh -s ${ROM_IMAGE} | cut -c 1-20 | tr -d '\n' + fi +} + update_checksums() { TRACE "Under /etc/functions:update_checksums" @@ -484,6 +563,27 @@ 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 "$*" }"; diff --git a/initrd/etc/gui_functions b/initrd/etc/gui_functions index d1920bd30..7c7a347f7 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" @@ -72,3 +83,41 @@ file_selector() 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/')" 16 60 +} + +# 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..54f59de9e 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 @@ -121,6 +120,13 @@ if [ "$boot_option" = "r" ]; then exit fi +# 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. # @@ -129,9 +135,17 @@ fi 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 +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 ' ') # chop off date, since will always be epoch w/timeless builds @@ -143,6 +157,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 diff --git a/modules/coreboot b/modules/coreboot index 5410e0846..7f5468f26 100644 --- a/modules/coreboot +++ b/modules/coreboot @@ -47,6 +47,11 @@ else ifeq "$(CONFIG_COREBOOT_VERSION)" "talos_2" coreboot_commit_hash = 068ad520e4ae898d356add72ea7d2a13913b76ab 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..6ba94793a 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 := 1.1 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 := e14e604d7b8f64196700723d74f678c65c7d517dae4e077f9ad9ba3d19d63731 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 */