|
| 1 | +#!/usr/bin/env bash |
| 2 | + |
| 3 | +# These variables are all for the deguard tool. |
| 4 | +# They would need to be changed if using the tool for other devices like the T480s or with a different ME version... |
| 5 | +ME_delta="thinkpad_t480s" |
| 6 | +ME_version="11.6.0.1126" |
| 7 | +ME_sku="2M" |
| 8 | +ME_pch="LP" |
| 9 | + |
| 10 | +# Thunderbolt firmware offset in bytes to pad to 1M |
| 11 | +TBFW_SIZE=1048575 |
| 12 | + |
| 13 | +# Integrity checks for the vendor provided ME blob... |
| 14 | +ME_DOWNLOAD_HASH="ddfbc51430699e0dfcb24a60bcb5b6e5481b325ebecf1ac177e069013189e4b0" |
| 15 | +# ...and the cleaned and deguarded version from that blob. |
| 16 | +DEGUARDED_ME_BIN_HASH="7bc47ed1ead1d72a135e7adff207ae8ddddc56d81128d9d6a8061ad04685c73b" |
| 17 | +# Integrity checks for the vendor provided Thunderbolt blob... |
| 18 | +TB_DOWNLOAD_HASH="090d0085af4a20bcdfba8a75f1bce735ff80afbfea968bbe276a80a0c4c18706" |
| 19 | +# ...and the padded and flashable version from that blob. |
| 20 | +TB_BIN_HASH="b53e4670327e076ef879b2abef0efd9aade20da88d0c0976921b9f32378c0119" |
| 21 | + |
| 22 | + |
| 23 | +function usage() { |
| 24 | + echo -n \ |
| 25 | + "Usage: $(basename "$0") -m <me_cleaner>(optional) path_to_output_directory |
| 26 | +Download Intel ME firmware from Dell, neutralize and shrink keeping the MFS. |
| 27 | +Download Thunderbolt firmware from Lenovo and pad it for flashing externally. |
| 28 | +" |
| 29 | +} |
| 30 | + |
| 31 | +function chk_sha256sum() { |
| 32 | + sha256_hash="$1" |
| 33 | + filename="$2" |
| 34 | + echo "$sha256_hash" "$filename" "$(pwd)" |
| 35 | + sha256sum "$filename" |
| 36 | + if ! echo "${sha256_hash} ${filename}" | sha256sum --check; then |
| 37 | + echo "ERROR: SHA256 checksum for ${filename} doesn't match." |
| 38 | + exit 1 |
| 39 | + fi |
| 40 | +} |
| 41 | + |
| 42 | +function chk_exists_and_matches() { |
| 43 | + if [[ -f "$1" ]]; then |
| 44 | + if echo "${2} ${1}" | sha256sum --check; then |
| 45 | + echo "SKIPPING: SHA256 checksum for $1 matches." |
| 46 | + [[ "$3" = ME ]] && me_exists="y" |
| 47 | + [[ "$3" = TB ]] && tb_exists="y" |
| 48 | + fi |
| 49 | + echo "$1 exists but checksum doesn't match. Continuing..." |
| 50 | + fi |
| 51 | +} |
| 52 | + |
| 53 | +function download_and_clean() { |
| 54 | + me_cleaner="$(realpath "${1}")" |
| 55 | + me_output="$(realpath "${2}")" |
| 56 | + |
| 57 | + # Download and unpack the Dell installer into a temporary directory and |
| 58 | + # extract the deguardable Intel ME blob. |
| 59 | + pushd "$(mktemp -d)" || exit |
| 60 | + |
| 61 | + # Download the installer that contains the ME blob |
| 62 | + me_installer_filename="Inspiron_5468_1.3.0.exe" |
| 63 | + user_agent="Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0" |
| 64 | + curl -A "$user_agent" -s -O "https://dl.dell.com/FOLDER04573471M/1/${me_installer_filename}" |
| 65 | + chk_sha256sum "$ME_DOWNLOAD_HASH" "$me_installer_filename" |
| 66 | + |
| 67 | + # Download the tool to unpack Dell's installer and unpack the ME blob. |
| 68 | + git clone https://github.com/platomav/BIOSUtilities |
| 69 | + git -C BIOSUtilities checkout ef50b75ae115ae8162fa8b0a7b8c42b1d2db894b |
| 70 | + |
| 71 | + python "BIOSUtilities/Dell_PFS_Extract.py" "${me_installer_filename}" -e || exit |
| 72 | + |
| 73 | + extracted_me_filename="1 Inspiron_5468_1.3.0 -- 3 Intel Management Engine (Non-VPro) Update v${ME_version}.bin" |
| 74 | + |
| 75 | + # Neutralize and shrink Intel ME. Note that this doesn't include |
| 76 | + # --soft-disable to set the "ME Disable" or "ME Disable B" (e.g., |
| 77 | + # High Assurance Program) bits, as they are defined within the Flash |
| 78 | + # Descriptor. |
| 79 | + # However, the HAP bit must be enabled to make the deguarded ME work. We only clean the ME in this function. |
| 80 | + # https://github.com/corna/me_cleaner/wiki/External-flashing#neutralize-and-shrink-intel-me-useful-only-for-coreboot |
| 81 | + |
| 82 | + # MFS is needed for deguard so we whitelist it here and also do not relocate the FTPR partition |
| 83 | + python "$me_cleaner" --whitelist MFS -t -O "$me_output" "${me_installer_filename}_extracted/Firmware/${extracted_me_filename}" |
| 84 | + rm -rf ./* |
| 85 | + popd || exit |
| 86 | +} |
| 87 | + |
| 88 | +function deguard() { |
| 89 | + me_input="$(realpath "${1}")" |
| 90 | + me_output="$(realpath "${2}")" |
| 91 | + |
| 92 | + # Download the deguard tool into a temporary directory and apply the patch to the cleaned ME blob. |
| 93 | + pushd "$(mktemp -d)" || exit |
| 94 | + git clone https://github.com/coreboot/deguard |
| 95 | + pushd deguard || exit |
| 96 | + git checkout 0ed3e4ff824fc42f71ee22907d0594ded38ba7b2 |
| 97 | + |
| 98 | + python ./finalimage.py \ |
| 99 | + --delta "data/delta/$ME_delta" \ |
| 100 | + --version "$ME_version" \ |
| 101 | + --pch "$ME_pch" \ |
| 102 | + --sku "$ME_sku" \ |
| 103 | + --fake-fpfs data/fpfs/zero \ |
| 104 | + --input "$me_input" \ |
| 105 | + --output "$me_output" |
| 106 | + |
| 107 | + popd || exit |
| 108 | + #Cleanup |
| 109 | + rm -rf ./* |
| 110 | + popd || exit |
| 111 | +} |
| 112 | + |
| 113 | +function download_and_pad_tb() { |
| 114 | + tb_output="$(realpath "${1}")" |
| 115 | + |
| 116 | + # Download and unpack the Lenovo installer into a temporary directory and |
| 117 | + # extract the TB blob. |
| 118 | + pushd "$(mktemp -d)" || exit |
| 119 | + |
| 120 | + # Download the installer that contains the T480s TB blob |
| 121 | + tb_installer_filename=""n22th11w.exe"" |
| 122 | + user_agent="Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0" |
| 123 | + curl -A "$user_agent" -s -O "https://download.lenovo.com/pccbbs/mobiles/${tb_installer_filename}" |
| 124 | + chk_sha256sum "$TB_DOWNLOAD_HASH" "$tb_installer_filename" |
| 125 | + |
| 126 | + # https://www.reddit.com/r/thinkpad/comments/9rnimi/ladies_and_gentlemen_i_present_to_you_the/ |
| 127 | + innoextract n22th11w.exe -d . |
| 128 | + mv ./code\$GetExtractPath\$/TBT.bin tb.bin |
| 129 | + # pad with zeros |
| 130 | + dd if=/dev/zero of=tb.bin bs=1 seek="$TBFW_SIZE" count=1 |
| 131 | + mv "tb.bin" "$tb_output" |
| 132 | + |
| 133 | + rm -rf ./* |
| 134 | + popd || exit |
| 135 | +} |
| 136 | + |
| 137 | +function usage_err() { |
| 138 | + echo "$1" |
| 139 | + usage |
| 140 | + exit 1 |
| 141 | +} |
| 142 | + |
| 143 | +function parse_params() { |
| 144 | + while getopts ":m:" opt; do |
| 145 | + case $opt in |
| 146 | + m) |
| 147 | + if [[ -x "$OPTARG" ]]; then |
| 148 | + me_cleaner="$OPTARG" |
| 149 | + fi |
| 150 | + ;; |
| 151 | + ?) |
| 152 | + usage_err "Invalid Option: -$OPTARG" |
| 153 | + ;; |
| 154 | + esac |
| 155 | + done |
| 156 | + |
| 157 | + if [[ -z "${me_cleaner}" ]]; then |
| 158 | + if [[ -z "${COREBOOT_DIR}" ]]; then |
| 159 | + usage_err "ERROR: me_cleaner.py not found. Set path with -m parameter or define the COREBOOT_DIR variable." |
| 160 | + else |
| 161 | + me_cleaner="${COREBOOT_DIR}/util/me_cleaner/me_cleaner.py" |
| 162 | + fi |
| 163 | + fi |
| 164 | + echo "Using me_cleaner from ${me_cleaner}" |
| 165 | + |
| 166 | + shift $(($OPTIND - 1)) |
| 167 | + output_dir="$(realpath "${1:-./}")" |
| 168 | + if [[ ! -d "${output_dir}" ]]; then |
| 169 | + usage_err "No valid output dir found" |
| 170 | + fi |
| 171 | + me_cleaned="${output_dir}/me_cleaned.bin" |
| 172 | + me_deguarded="${output_dir}/t480s_me.bin" |
| 173 | + tb_flashable="${output_dir}/t480s_tb.bin" |
| 174 | + echo "Writing cleaned and deguarded ME to ${me_deguarded}" |
| 175 | + echo "Writing flashable TB to ${tb_flashable}" |
| 176 | +} |
| 177 | + |
| 178 | +if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then |
| 179 | + if [[ "${1:-}" == "--help" ]]; then |
| 180 | + usage |
| 181 | + exit 0 |
| 182 | + fi |
| 183 | + |
| 184 | + parse_params "$@" |
| 185 | + chk_exists_and_matches "$me_deguarded" "$DEGUARDED_ME_BIN_HASH" ME |
| 186 | + chk_exists_and_matches "$tb_flashable" "$TB_BIN_HASH" TB |
| 187 | + |
| 188 | + if [[ -z "$me_exists" ]]; then |
| 189 | + download_and_clean "$me_cleaner" "$me_cleaned" |
| 190 | + deguard "$me_cleaned" "$me_deguarded" |
| 191 | + rm -f "$me_cleaned" |
| 192 | + fi |
| 193 | + |
| 194 | + if [[ -z "$tb_exists" ]]; then |
| 195 | + download_and_pad_tb "$tb_flashable" |
| 196 | + fi |
| 197 | + |
| 198 | + chk_sha256sum "$DEGUARDED_ME_BIN_HASH" "$me_deguarded" |
| 199 | + chk_sha256sum "$TB_BIN_HASH" "$tb_flashable" |
| 200 | +fi |
0 commit comments