227 lines
5.2 KiB
Bash
Executable File
227 lines
5.2 KiB
Bash
Executable File
#!/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
|
|
|
|
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"
|
|
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
|
|
|
|
# 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
|
|
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/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"
|
|
;;
|
|
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 || return 1
|
|
Extract_me || return 1
|
|
|
|
return 0
|
|
}
|
|
|
|
Fetch_update() {
|
|
printf "Fetching vendor update for board: `%s`\n" ${board}
|
|
|
|
if [ -z "${dl_url+x}" ]; then
|
|
printf "No vendor update specified for board: `%s`\n" ${board}
|
|
return 1
|
|
fi
|
|
|
|
Vendor_checksum ${dl_path} || \
|
|
curl ${dl_url} > ${dl_path} || curl ${dl_url_bkup} > ${dl_path}
|
|
|
|
Vendor_checksum ${dl_path} || Fail \
|
|
"Cannot guarantee intergity of vendor update for board: `${board}`"
|
|
|
|
return 0
|
|
}
|
|
|
|
Vendor_checksum() {
|
|
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}')" != "${dl_hash}" ]; then
|
|
printf "Bad checksum on vendor update for board: `%s`\n" ${board}
|
|
rm ${dl_path}
|
|
return 1
|
|
fi
|
|
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
|
|
|
|
(
|
|
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 "${_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
|
|
)
|
|
if [ ! -f "${_me_destination}" ]; then
|
|
printf "me.bin not found in vendor update for board: `%s`\n" ${board}
|
|
return 1
|
|
else
|
|
return 0
|
|
fi
|
|
}
|
|
|
|
Main
|