Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ jobs:
command: |
./blobs/xx80/t480_download_clean_deguard_me_pad_tb.sh -m $(readlink -f ./blobs/utils/me_cleaner/me_cleaner.py) ./blobs/xx80/
./blobs/xx80/t480s_download_clean_deguard_me_pad_tb.sh -m $(readlink -f ./blobs/utils/me_cleaner/me_cleaner.py) ./blobs/xx80/
./blobs/xx80/x280_download_clean_deguard_me_pad_tb.sh -m $(readlink -f ./blobs/utils/me_cleaner/me_cleaner.py) ./blobs/xx80/
- run:
name: Download, neuter and deguard m900 ME (keep generated GBE and extracted IFD in tree)
command: |
Expand Down Expand Up @@ -476,6 +477,15 @@ workflows:
requires:
- x86-musl-cross-make [cross compiler]

# 25.12 fork — builds coreboot-25.12 toolchain
- x86_coreboot:
name: EOL_x280-hotp-maximized [seed:coreboot-25.12]
target: EOL_x280-hotp-maximized
subcommand: ""
coreboot_dir: coreboot-25.12
requires:
- x86-musl-cross-make [cross compiler]

# ── Dasharo shared toolchain ──────────────────────────────────────────
# 4 forks share crossgcc (verified by sum-file diff).
# novacustom-nv4x_adl is the only seed; all other Dasharo boards are
Expand Down Expand Up @@ -527,6 +537,22 @@ workflows:
requires:
- x86-musl-cross-make [cross compiler]

# ── coreboot 25.12 boards X280 acts as seed ───────────────────────────────

- build:
name: EOL_x280-hotp-maximized
target: EOL_x280-hotp-maximized
subcommand: ""
requires:
- EOL_x280-hotp-maximized [seed:coreboot-25.12]

- build:
name: EOL_x280-maximized
target: EOL_x280-maximized
subcommand: ""
requires:
- EOL_x280-hotp-maximized [seed:coreboot-25.12]

# ── coreboot 25.09 boards (alphabetical) ───────────────────────────────
- build:
name: EOL_m900_tower-hotp-maximized
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
*~
.*.sw*
/.direnv
*.bin
clean
config/*.old
crossgcc
Expand Down
3 changes: 2 additions & 1 deletion blobs/xx80/README.md

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should not be deleted?

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# T480 Blobs
# xx80 Blobs

The following blobs are needed:

Expand All @@ -22,6 +22,7 @@ As specified in the first link, this ME can be deployed to:

* T480
* T480s
* X280

## ifd.bin and gbe.bin

Expand Down
5 changes: 5 additions & 0 deletions blobs/xx80/hashes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,8 @@ f2f6d5fb0a5e02964b494862032fd93f1f88e2febd9904b936083600645c7fdf t480_ifd.bin
b53e4670327e076ef879b2abef0efd9aade20da88d0c0976921b9f32378c0119 t480s_tb.bin
caf6393cd5c4ff305b677f50c258658710c42439080868c1fb8ea7584cffb204 t480s_ifd.bin
36be39ecd0d06fa3f7893ca2746f702271c46b75de52bc599467a058bab8e271 t480s_gbe.bin
#X280:
fc67c1cafd11666a2f2702232e887ca413ce146ee25ec246ca94e60ac3083313 x280_tb.bin
404e08c7c9a4fd43c3b4da82012340ae360b3fbe299f4cb6b75344054d5fc936 x280_me.bin
4f0d11e9d62fe4d22fe2108ff35764f1bf2ad9131965e85f3cd43d6a1e83bb63 x280_ifd.bin
67ca8a1e91d31bb992bf8fddc1636b1df682bbb285b2c0701cfb4565924b8103 x280_gbe.bin
206 changes: 206 additions & 0 deletions blobs/xx80/x280_download_clean_deguard_me_pad_tb.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
#!/usr/bin/env bash

# These variables are all for the deguard tool.
# They would need to be changed if using the tool for other devices like the X280 or with a different ME version...
ME_delta="thinkpad_x280"
ME_version="11.6.0.1126"
ME_sku="2M"
ME_pch="LP"

# Thunderbolt firmware offset in bytes to pad to 1M
TBFW_SIZE=1048575

# Integrity checks for the vendor provided ME blob...
ME_DOWNLOAD_HASH="ddfbc51430699e0dfcb24a60bcb5b6e5481b325ebecf1ac177e069013189e4b0"
# ...and the cleaned and deguarded version from that blob.
# DEGUARDED_ME_BIN_HASH="404e08c7c9a4fd43c3b4da82012340ae360b3fbe299f4cb6b75344054d5fc936"
DEGUARDED_ME_BIN_HASH="6f1221c936a1bed60c057883d231d48ef23c4fa9"
# Integrity checks for the vendor provided Thunderbolt blob...
# still not sure it'll work
TB_DOWNLOAD_HASH="dcefadd999684d13a7909ee0bac17964209a6c4e6ebf5609ba72f9dab5e1d5b5"
# ...and the padded and flashable version from that blob.
# still not sure it'll work
TB_BIN_HASH="fc67c1cafd11666a2f2702232e887ca413ce146ee25ec246ca94e60ac3083313"

function usage() {
echo -n \
"Usage: $(basename "$0") -m <me_cleaner>(optional) path_to_output_directory
Download Intel ME firmware from Dell, neutralize and shrink keeping the MFS.
Download Thunderbolt firmware from Lenovo and pad it for flashing externally.
"
}

function chk_sha256sum() {
sha256_hash="$1"
filename="$2"
echo "$sha256_hash" "$filename" "$(pwd)"
sha256sum "$filename"
if ! echo "${sha256_hash} ${filename}" | sha256sum --check; then
echo "ERROR: SHA256 checksum for ${filename} doesn't match."

fi
}

function chk_exists_and_matches() {
if [[ -f "$1" ]]; then
if echo "${2} ${1}" | sha256sum --check; then
echo "SKIPPING: SHA256 checksum for $1 matches."
[[ "$3" = ME ]] && me_exists="y"
[[ "$3" = TB ]] && tb_exists="y"
fi
echo "$1 exists but checksum doesn't match. Continuing..."
fi
}

function download_and_clean() {
me_cleaner="$(realpath "${1}")"
me_output="$(realpath "${2}")"

# Download and unpack the Dell installer into a temporary directory and
# extract the deguardable Intel ME blob.
pushd "$(mktemp -d)" || exit

# Download the installer that contains the ME blob
me_installer_filename="Inspiron_5468_1.3.0.exe"
user_agent="Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0"
curl -A "$user_agent" -s -O "https://dl.dell.com/FOLDER04573471M/1/${me_installer_filename}"
chk_sha256sum "$ME_DOWNLOAD_HASH" "$me_installer_filename"

# Download the tool to unpack Dell's installer and unpack the ME blob.
git clone https://github.com/platomav/BIOSUtilities
git -C BIOSUtilities checkout ef50b75ae115ae8162fa8b0a7b8c42b1d2db894b

python "BIOSUtilities/Dell_PFS_Extract.py" "${me_installer_filename}" -e || exit

extracted_me_filename="1 Inspiron_5468_1.3.0 -- 3 Intel Management Engine (Non-VPro) Update v${ME_version}.bin"

# Deactivate, partially neuter and shrink Intel ME. Note that this doesn't include
# --soft-disable to set the "ME Disable" or "ME Disable B" (e.g.,
# High Assurance Program) bits, as they are defined within the Flash
# Descriptor.
# However, the HAP bit must be enabled to make the deguarded ME work. We only clean the ME in this function.
# For ME 11.x this means we must keep the rbe, bup, kernel and syslib modules.
# https://github.com/corna/me_cleaner/wiki/How-does-it-work%3F#me-versions-from-11x-skylake-1
# Furthermore, deguard requires keeping the MFS, the HAP bit set, and we cannot relocate the FTPR partition.
# Some more general info on shrinking:
# https://github.com/corna/me_cleaner/wiki/External-flashing#neutralize-and-shrink-intel-me-useful-only-for-coreboot

# MFS is needed for deguard so we whitelist it here and also do not relocate the FTPR partition
python "$me_cleaner" --whitelist MFS -t -O "$me_output" "${me_installer_filename}_extracted/Firmware/${extracted_me_filename}"
rm -rf ./*
popd || exit
}

function deguard() {
me_input="$(realpath "${1}")"
me_output="$(realpath "${2}")"

# Download the deguard tool into a temporary directory and apply the patch to the cleaned ME blob.
pushd "$(mktemp -d)" || exit
git clone https://github.com/coreboot/deguard
pushd deguard || exit
git checkout 4944584c7cc0201adcc89a0465ab60f7f9f50ac6

python ./finalimage.py \
--delta "data/delta/$ME_delta" \
--version "$ME_version" \
--pch "$ME_pch" \
--sku "$ME_sku" \
--fake-fpfs data/fpfs/zero \
--input "$me_input" \
--output "$me_output"

popd || exit
#Cleanup
rm -rf ./*
popd || exit
}

function download_and_pad_tb() {
tb_output="$(realpath "${1}")"

# Download and unpack the Lenovo installer into a temporary directory and
# extract the TB blob.
pushd "$(mktemp -d)" || exit

# Download the installer that contains the TB blob
tb_installer_filename=""n20th12w.exe""
user_agent="Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0"
curl -A "$user_agent" -s -O "https://download.lenovo.com/pccbbs/mobiles/${tb_installer_filename}"
chk_sha256sum "$TB_DOWNLOAD_HASH" "$tb_installer_filename"

# https://www.reddit.com/r/thinkpad/comments/9rnimi/ladies_and_gentlemen_i_present_to_you_the/
innoextract n20th12w.exe -d .
mv ./code\$GetExtractPath\$/TBT.bin tb.bin
# pad with zeros
dd if=/dev/zero of=tb.bin bs=1 seek="$TBFW_SIZE" count=1
mv "tb.bin" "$tb_output"

rm -rf ./*
popd || exit
}

function usage_err() {
echo "$1"
usage
exit 1
}

function parse_params() {
while getopts ":m:" opt; do
case $opt in
m)
if [[ -x "$OPTARG" ]]; then
me_cleaner="$OPTARG"
fi
;;
?)
usage_err "Invalid Option: -$OPTARG"
;;
esac
done

if [[ -z "${me_cleaner}" ]]; then
if [[ -z "${COREBOOT_DIR}" ]]; then
usage_err "ERROR: me_cleaner.py not found. Set path with -m parameter or define the COREBOOT_DIR variable."
else
me_cleaner="${COREBOOT_DIR}/util/me_cleaner/me_cleaner.py"
fi
fi
echo "Using me_cleaner from ${me_cleaner}"

shift $(($OPTIND - 1))
output_dir="$(realpath "${1:-./}")"
if [[ ! -d "${output_dir}" ]]; then
usage_err "No valid output dir found"
fi
me_cleaned="${output_dir}/me_cleaned.bin"
me_deguarded="${output_dir}/x280_me.bin"
tb_flashable="${output_dir}/x280_tb.bin"
echo "Writing cleaned and deguarded ME to ${me_deguarded}"
echo "Writing flashable TB to ${tb_flashable}"
}

if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
if [[ "${1:-}" == "--help" ]]; then
usage
exit 0
fi

parse_params "$@"
chk_exists_and_matches "$me_deguarded" "$DEGUARDED_ME_BIN_HASH" ME
chk_exists_and_matches "$tb_flashable" "$TB_BIN_HASH" TB

if [[ -z "$me_exists" ]]; then
download_and_clean "$me_cleaner" "$me_cleaned"
deguard "$me_cleaned" "$me_deguarded"
rm -f "$me_cleaned"
fi

if [[ -z "$tb_exists" ]]; then
download_and_pad_tb "$tb_flashable"
fi

chk_sha256sum "$DEGUARDED_ME_BIN_HASH" "$me_deguarded"
chk_sha256sum "$TB_BIN_HASH" "$tb_flashable"
fi
Binary file added blobs/xx80/x280_gbe.bin
Binary file not shown.
Binary file added blobs/xx80/x280_ifd.bin
Binary file not shown.
94 changes: 94 additions & 0 deletions boards/EOL_x280-hotp-maximized/EOL_x280-hotp-maximized.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# WARNING: This system remains perpetually vulnerable to Spectre v2 (CVE-2017-5715). Mitigations and microcode updates previously applied are now known to be ineffective due to QSB-107 and related CVEs. If Spectre v2 is a concern in your threat model, consider migrating to a platform with ongoing microcode support. Proper OPSEC for Memory Use MUST be followed:https://www.anarsec.guide/posts/qubes/#appendix-opsec-for-memory-use
# Configuration for a T480 running Qubes 4.2.3 and other Linux Based OSes (through kexec)
#
# CAVEATS: TPM_GPIO_RESET=VULNERABLE -- TOTP/HOTP secret extractable, DUK with passphrase safe
# See doc/TPM_GPIO_Reset_Vulnerability.md for details.
# - Deactivated+partially neutered+deguarded ME and expanded consequent IFD BIOS regions
# - More details can be found in the script under blobs/xx80/download_clean_deguard_me_pad_tb.sh
# - Forged GBE MAC address to 00:DE:AD:C0:FF:EE MAC address (if not extracting gbe.bin from backup with blobs/xx80/extract.sh)
# - Note that this MAC address can be modified under build/coreboot-VER/util/bincfg/gbe-82579LM.set
# - Flashable Thunderbolt tb.bin blob extracted from https://download.lenovo.com/pccbbs/mobiles/n24th13w.exe
# - It is zero-padded to 1MB and should be flashed to the Thunderbolt SPI chip,
# which is not the same as the 16MB chip to which the heads rom is flashed.
# External flashing is recommended as the only way to reliably fix a bug in the original Thunderbolt software on the SPI chip.
# You can find a guide here: https://osresearch.net/T480-maximized-flashing/
#
# - Includes Nitrokey/Librem Key HOTP Security dongle remote attestation (in addition to TOTP remote attestation through Qr Code)

export CONFIG_COREBOOT=y
export CONFIG_COREBOOT_VERSION=25.12
export CONFIG_LINUX_VERSION=6.1.8

CONFIG_COREBOOT_CONFIG=config/coreboot-x280-maximized.config
CONFIG_LINUX_CONFIG=config/linux-x280.config

#On-demand hardware support (modules.cpio)
CONFIG_LINUX_USB=y
CONFIG_LINUX_E1000E=y
CONFIG_MOBILE_TETHERING=y

#Modules packed into tools.cpio
CONFIG_CRYPTSETUP2=y
CONFIG_FLASHPROG=y
CONFIG_FLASHTOOLS=y
CONFIG_GPG2=y
CONFIG_KEXEC=y
CONFIG_UTIL_LINUX=y
CONFIG_LVM2=y
CONFIG_MBEDTLS=y
CONFIG_PCIUTILS=y

#platform locking finalization (PR0)
CONFIG_IO386=y
export CONFIG_FINALIZE_PLATFORM_LOCKING=y


#Remote attestation support
# TPM2 requirements
CONFIG_TPM2_TSS=y
CONFIG_OPENSSL=y
#Remote Attestation common tools
CONFIG_POPT=y
CONFIG_QRENCODE=y
CONFIG_TPMTOTP=y
#HOTP based remote attestation for supported USB Security dongle
#With/Without TPM support
CONFIG_HOTPKEY=y
#Nitrokey Storage admin tool (deprecated)
#CONFIG_NKSTORECLI=n

#GUI Support
#Console based Whiptail support(Console based, no FB):
#CONFIG_SLANG=y
#CONFIG_NEWT=y
#FBWhiptail based (Graphical):
CONFIG_CAIRO=y
CONFIG_FBWHIPTAIL=y

#Additional tools (tools.cpio):
#SSH server (requires ethernet drivers, eg: CONFIG_LINUX_E1000E)
#CONFIG_DROPBEAR=y

#Runtime configuration
#Automatically boot if HOTP is valid
export CONFIG_AUTO_BOOT_TIMEOUT=5
#TPM2 requirements
export CONFIG_TPM2_TOOLS=y
export CONFIG_PRIMARY_KEY_TYPE=ecc
#TPM1 requirements
#export CONFIG_TPM=y
export CONFIG_DEBUG_OUTPUT=n
export CONFIG_ENABLE_FUNCTION_TRACING_OUTPUT=n
#Enable TPM2 pcap output under /tmp
export CONFIG_TPM2_CAPTURE_PCAP=n
#Enable quiet mode: technical information logged under /tmp/debug.log
export CONFIG_QUIET_MODE=y
export CONFIG_BOOTSCRIPT=/bin/gui-init.sh
export CONFIG_BOOT_REQ_HASH=n
export CONFIG_BOOT_REQ_ROLLBACK=n
export CONFIG_BOOT_KERNEL_ADD=""
export CONFIG_BOOT_KERNEL_REMOVE="intel_iommu=on intel_iommu=igfx_off"
export CONFIG_BOARD_NAME="Thinkpad X280-hotp-maximized"
export CONFIG_FLASH_OPTIONS="flashprog --progress --programmer internal"

BOARD_TARGETS := x280_me_blobs
Loading