123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334 |
- #!/usr/bin/env sh
- # SPDX-FileCopyrightText: 2022 Caleb La Grange <thonkpeasant@protonmail.com>
- # SPDX-FileCopyrightText: 2022 Ferass El Hafidi <vitali64pmemail@protonmail.com>
- # SPDX-FileCopyrightText: 2023 Leah Rowe <info@minifree.org>
- # SPDX-License-Identifier: GPL-3.0-only
- ec_url=""
- ec_url_bkup=""
- ec_hash=""
- blobdir="blobs"
- dl_path="${blobdir}/vendorupdate"
- appdir="${blobdir}/app"
- _7ztest="a"
- mecleaner="$(pwd)/me_cleaner/me_cleaner.py"
- me7updateparser="$(pwd)/resources/blobs/me7_update_parser.py"
- kbc1126_ec_dump="$(pwd)/coreboot/default/util/kbc1126/kbc1126_ec_dump"
- board="${1}"
- # A shorthand for each board, to avoid duplicating configs per flash size
- board_short=${board%%_*mb}
- set -- "resources/coreboot/${board}/config/*"
- . ${1} 2>/dev/null
- . "resources/coreboot/${board}/board.cfg"
- if [ "${CONFIG_HAVE_MRC}" = "y" ]; then
- printf 'haswell board detected, downloading mrc\n'
- needs="${needs} MRC"
- fi
- if [ "${CONFIG_HAVE_IFD_BIN}" = "y" ]; then
- printf 'board needs intel firmware descriptor\n'
- needs="${needs} IFD"
- fi
- if [ "${CONFIG_HAVE_ME_BIN}" = "y" ]; then
- printf 'board needs intel management engine\n'
- needs="${needs} ME"
- fi
- if [ "${CONFIG_HAVE_GBE_BIN}" = "y" ]; then
- printf 'board needs gigabit ethernet firmware\n'
- needs="${needs} GBE"
- fi
- if [ "${CONFIG_KBC1126_FIRMWARE}" = "y" ]; then
- printf "HP board with KBC1126 EC detected, downloading ec\n"
- needs="${needs} EC"
- fi
- # Quickly exit without wasting more time if there are no blobs needed (GM45)
- if [ -z ${needs+x} ]; then
- printf 'No binary blobs needed for this board\n'
- exit 0
- fi
- while read -r line ; do
- case ${line} in
- EC_url*)
- set ${line}
- ec_url=${2}
- ;;
- EC_url_bkup*)
- set ${line}
- ec_url_bkup=${2}
- ;;
- EC_hash*)
- set ${line}
- ec_hash=${2}
- ;;
- DL_hash*)
- set ${line}
- dl_hash=${2}
- ;;
- DL_url*)
- set ${line}
- dl_url=${2}
- ;;
- DL_url_bkup*)
- set ${line}
- dl_url_bkup=${2}
- ;;
- esac
- done << EOF
- $(eval "awk ' /\{.*${board_short}.*}{/ {flag=1;next} /\}/{flag=0} flag { print }' resources/blobs/sources")
- EOF
- Main() {
- Build_deps
- Download_needed
- }
- Fail(){
- printf "\nERROR: $@\n"
- exit 1
- }
- Build_deps(){
- if [ ! -d me_cleaner ]; then
- printf "downloading me_cleaner\n"
- ./download me_cleaner || Fail 'could not download me_cleaner'
- fi
- if [ ! -d coreboot/default ]; then
- printf "downloading coreboot\n"
- ./download coreboot default || Fail 'could not download coreboot'
- fi
- if [ ! -f coreboot/default/util/kbc1126/kbc1126_ec_dump ]; then
- printf "Building kbc1126_ec_dump from coreboot\n"
- make -BC coreboot/default/util/kbc1126 || Fail \
- "could not build kbc1126_ec_dump"
- fi
-
- if [ ! -f "coreboot/default/util/ifdtool/ifdtool" ]; then
- printf "building ifdtool from coreboot\n"
- make -C coreboot/default/util/ifdtool || Fail 'could not build ifdtool'
- fi
- }
- Download_needed(){
- for need in ${needs}; do
- case ${need} in
- *ME*)
- Download_me || _failed="${_failed} me"
- ;;
- *MRC*)
- ./download mrc || _failed="${_failed} mrc"
- ;;
- *EC*)
- Download_ec || _failed="${_failed} ec"
- ;;
- esac
- done
-
- if [ ! -z ${_failed+x} ]; then
- Fail "failed to obtain ${_failed}\nYou may try manually extracting blobs with './blobutil extract'"
- fi
- }
- Download_me() {
- printf "Downloading neutered ME for board: %s\n" ${board}
- Fetch_update me || return 1
- Extract_me || return 1
- return 0
- }
- Extract_me(){
- printf "Extracting neutered ME for ${board}\n"
- _me_destination=${CONFIG_ME_BIN_PATH#../../}
- if [ ! -d "${_me_destination%/*}" ]; then
- mkdir -p ${_me_destination%/*}
- fi
-
- if [ -d "${appdir}" ]; then
- rm -r ${appdir}
- fi
- if [ -f "${_me_destination}" ]; then
- printf 'me already downloaded\n'
- return 0
- fi
- printf 'extracting and stripping intel management engine\n'
- innoextract ${dl_path} -d ${blobdir} \
- || 7z x ${dl_path} -o${appdir} \
- || Fail 'could not extract me executable with innoextract'
- Bruteforce_extract_me "$(pwd)/${_me_destination}" "$(pwd)/${appdir}" \
- || return 1
- printf "Truncated and cleaned me output to ${_me_destination}\n"
- return 0
- }
- # cursed, carcinogenic code. TODO rewrite it better
- Bruteforce_extract_me() {
- _me_destination="${1}"
- cdir="${2}" # must be an absolute path, not relative
- if [ -f "${_me_destination}" ]; then
- return 0
- fi
- sdir="$(mktemp -d)"
- mkdir -p "${sdir}" || return 1
- (
- printf "Entering %s\n" "${cdir}"
- cd "${cdir}" || exit 1
- for i in *; do
- if [ -f "${_me_destination}" ]; then
- # me.bin found, so avoid needless further traversal
- break
- elif [ -L "${i}" ]; then
- # symlinks are a security risk, in this context
- continue
- elif [ -f "${i}" ]; then
- "${mecleaner}" -r -t -O "${sdir}/vendorfile" -M "${_me_destination}" "${i}" \
- && break # (we found me.bin)
- "${mecleaner}" -r -t -O "${_me_destination}" "${i}" \
- && break # (we found me.bin)
- "${me7updateparser}" -O ${_me_destination} "${i}" \
- && break
- _7ztest="${_7ztest}a"
- 7z x "${i}" -o${_7ztest} || continue
- Bruteforce_extract_me "${_me_destination}" "${cdir}/${_7ztest}"
- cdir="${1}"
- cd "${cdir}"
- elif [ -d "$i" ]; then
- Bruteforce_extract_me "${_me_destination}" "${cdir}/${i}"
- cdir="${1}"
- cd "${cdir}"
- else
- printf "SKIPPING: %s\n" "${i}"
- fi
- done
- )
- rm -Rf "${sdir}"
- if [ ! -f "${_me_destination}" ]; then
- printf "me.bin not found in vendor update for board: %s\n" ${board}
- return 1
- else
- return 0
- fi
- }
- Download_ec() {
- printf "Downloading KBC1126 EC firmware for HP laptop\n"
- Fetch_update ec || return 1
- Extract_ec || return 1
- return 0
- }
- Extract_ec() {
- printf "Extracting KBC1126 EC firmware for board: %s\n" ${board}
- _ec_destination=${CONFIG_KBC1126_FW1#../../}
- if [ ! -d "${_ec_destination%/*}" ]; then
- mkdir -p "${_ec_destination%/*}"
- fi
- if [ -d "${appdir}" ]; then
- rm -Rf "${appdir}"
- fi
- if [ -f "${_ec_destination}" ]; then
- printf "ec already downloaded\n"
- return 0
- fi
- unar "${dl_path}" -o "${appdir}"
- (
- cd "${appdir}/${dl_path##*/}"
- mv Rompaq/68*.BIN ec.bin
- "${kbc1126_ec_dump}" ec.bin
- )
- for i in 1 2; do
- if [ ! -f "${appdir}/${dl_path##*/}/ec.bin.fw${i}" ]; then
- printf "Not found: %s/%s/ec.bin.fw%s\n" \
- ${appdir} ${dl_path##*/} ${i}
- printf "Could not extract EC firmware for board: %s\n" \
- ${board}
- return 1
- fi
- done
- cp "${appdir}/${dl_path##*/}"/ec.bin.fw* "${_ec_destination%/*}/"
- }
- Fetch_update() {
- printf "Fetching vendor update for board: %s\n" ${board}
- fw_type="${1}"
- dl=""
- dl_bkup=""
- dlsum=""
- if [ "${fw_type}" = "me" ]; then
- dl=${dl_url}
- dl_bkup=${dl_url_bkup}
- dlsum=${dl_hash}
- elif [ "${fw_type}" = "ec" ]; then
- dl=${ec_url}
- dl_bkup=${ec_url_bkup}
- dlsum=${ec_hash}
- else
- printf "Unsupported download type: %s\n" ${fw_type}
- return 1
- fi
- if [ -z "${dl_url+x}" ]; then
- printf "No vendor update specified for board: %s\n" ${board}
- return 1
- fi
- Vendor_checksum ${dlsum} || \
- curl ${dl} > ${dl_path} || curl ${dl_bkup} > ${dl_path}
- Vendor_checksum ${dlsum} || Fail \
- "Cannot guarantee intergity of vendor update for board: ${board}"
- return 0
- }
- Vendor_checksum() {
- sha1=$1
- if [ ! -f "${dl_path}" ]; then
- printf "Vendor update not found on disk for board: %s\n" ${board}
- return 1
- fi
- if [ "$(sha1sum ${dl_path} | awk '{print $1}')" != "${sha1}" ]; then
- printf "Bad checksum on vendor update for board: %s\n" ${board}
- rm ${dl_path}
- return 1
- fi
- return 0
- }
- Main
|