#!/usr/bin/env sh # SPDX-License-Identifier: GPL-3.0-only # SPDX-FileCopyrightText: 2022 Caleb La Grange # SPDX-FileCopyrightText: 2022 Ferass El Hafidi # SPDX-FileCopyrightText: 2023 Leah Rowe . "include/err.sh" . "include/blobutil.sh" . "include/mrc.sh" export PATH="${PATH}:/sbin" main() { [ $# -gt 0 ] || err "No argument given" board="${1}" boarddir="${cbcfgsdir}/${board}" check_defconfig "${boarddir}" || exit 0 detect_firmware && exit 0 scan_sources_config build_dependencies download_blobs } detect_firmware() { set -- "${boarddir}/config/"* . "${1}" 2>/dev/null for c in CONFIG_HAVE_MRC CONFIG_HAVE_ME_BIN CONFIG_KBC1126_FIRMWARE \ CONFIG_VGA_BIOS_FILE CONFIG_INCLUDE_SMSC_SCH5545_EC_FW; do eval "[ -z \"\${${c}}\" ] || return 1" done printf "Blobs not needed for: %s\n" "${board}" 1>&2 } scan_sources_config() { _b=${board%%_*mb} # shorthand to avoid duplicating config per rom size awkstr=" /\{.*${_b}.*}{/ {flag=1;next} /\}/{flag=0} flag { print }" while read -r line ; do set ${line} 1>/dev/null 2>/dev/null eval "${1}=\"${2}\"" done << EOF $(eval "awk '${awkstr}' config/blobs/sources") EOF } build_dependencies() { [ -d ${cbdir} ] || ./update project trees coreboot ${cbdir##*/} || \ err "build_dependencies: can't fetch ${cbdir}" for d in uefitool biosutilities bios_extract me_cleaner; do [ -d "${d}" ] && continue ./update project repo "${d}" || \ err "build_dependencies: can't fetch ${d}" done [ -f uefitool/uefiextract ] || ./handle make file -b uefitool || \ err "build_dependencies: can't build uefitool" [ -f "${cbdir}/util/kbc1126/kbc1126_ec_dump" ] || \ make -C "${cbdir}/util/kbc1126" || \ err "build_dependencies: can't build kbc1126_ec_dump" ./build coreboot utils default || \ err "build_dependencies: cannot build utils in cbutils/default/" } download_blobs() { [ -z "${CONFIG_HAVE_ME_BIN}" ] || \ fetch "intel_me" "${DL_url}" "${DL_url_bkup}" "${DL_hash}" \ "${blobdir}/cache/${DL_hash}" "err" [ -z "${CONFIG_INCLUDE_SMSC_SCH5545_EC_FW}" ] || \ fetch "sch5545ec" "${SCH5545EC_DL_url}" \ "${SCH5545EC_DL_url_bkup}" "${SCH5545EC_DL_hash}" \ "${blobdir}/cache/${SCH5545EC_DL_hash}" "err" [ -z "${CONFIG_KBC1126_FIRMWARE}" ] || \ fetch "kbc1126ec" "${EC_url}" "${EC_url_bkup}" "${EC_hash}" \ "${blobdir}/cache/${EC_hash}" "err" [ -z "${CONFIG_VGA_BIOS_FILE}" ] || \ fetch "e6400vga" "${E6400_VGA_DL_url}" \ "${E6400_VGA_DL_url_bkup}" "${E6400_VGA_DL_hash}" \ "${blobdir}/cache/${E6400_VGA_DL_hash}" "err" if [ ! -z "${CONFIG_HAVE_MRC}" ]; then fetch "mrc" "${MRC_url}" "${MRC_url_bkup}" "${MRC_hash}" \ "${blobdir}/cache/${MRC_hash}" "err" fi } extract_intel_me() { _me_destination=${CONFIG_ME_BIN_PATH#../../} mkdirs "${_me_destination}" "extract_intel_me" || return 0 bruteforce_extract_intel_me "$(pwd)/${_me_destination}" \ "$(pwd)/${appdir}" || \ err "extract_intel_me: could not extract Intel ME firmware" if [ ! -f "${_me_destination}" ]; then err "extract_intel_me, ${board}: me.bin missing" fi } # cursed, carcinogenic code. TODO rewrite it better bruteforce_extract_intel_me() { _me_destination="${1}" cdir="${2}" # must be an absolute path, not relative [ -f "${_me_destination}" ] && return 0 sdir="$(mktemp -d)" mkdir -p "${sdir}" || return 1 ( cd "${cdir}" || err "bruteforce_extract_intel_me: !cd \"${cdir}\"" for i in *; do [ -f "${_me_destination}" ] && break [ -L "${i}" ] && continue if [ -f "${i}" ]; then "${mecleaner}" -r -t -O "${sdir}/vendorfile" \ -M "${_me_destination}" "${i}" && break "${mecleaner}" -r -t -O "${_me_destination}" "${i}" && \ break "${me7updateparser}" -O "${_me_destination}" "${i}" && \ break _7ztest="${_7ztest}a" extract_archive "${i}" "${_7ztest}" || continue bruteforce_extract_intel_me "${_me_destination}" \ "${cdir}/${_7ztest}" elif [ -d "$i" ]; then bruteforce_extract_intel_me "${_me_destination}" \ "${cdir}/${i}" else continue fi cdir="${1}" cd "${cdir}" done ) rm -Rf "${sdir}" || err "bruteforce_extract_intel_me: !rm -Rf ${sdir}" } extract_kbc1126ec() { _ec_destination=${CONFIG_KBC1126_FW1#../../} mkdirs "${_ec_destination}" "extract_kbc1126_ec" || return 0 ( cd "${appdir}/" || \ err "extract_kbc1126_ec: !cd \"${appdir}/\"" mv Rompaq/68*.BIN ec.bin || : if [ ! -f ec.bin ]; then unar -D ROM.CAB Rom.bin || unar -D Rom.CAB Rom.bin || \ unar -D 68*.CAB Rom.bin || err "extract_kbc1126_ec !extract" mv Rom.bin ec.bin || err "extract_kbc1126_ec: *didn't* extract" fi [ -f ec.bin ] || err "extract_kbc1126_ec ${board}: can't extract" "${kbc1126_ec_dump}" ec.bin || \ err "extract_kbc1126_ec ${board}: can't extract ecfw1/2.bin" ) ec_ex="y" for i in 1 2; do [ -f "${appdir}/ec.bin.fw${i}" ] || ec_ex="n" done [ "${ec_ex}" = "y" ] || \ err "extract_kbc1126_ec ${board}: didn't extract ecfw1/2.bin" cp "${appdir}/"ec.bin.fw* "${_ec_destination%/*}/" || \ err "extract_kbc1126_ec: cant mv ecfw1/2 ${_ec_destination%/*}" } extract_e6400vga() { _vga_destination=${CONFIG_VGA_BIOS_FILE#../../} mkdirs "${_vga_destination}" "extract_e6400vga" || return 0 [ "${E6400_VGA_offset}" = "" ] && \ err "extract_e6400vga: E6400 VGA offset not defined" [ "${E6400_VGA_romname}" = "" ] && \ err "extract_e6400vga: E6400 VGA ROM name not defined" tail -c +${E6400_VGA_offset} "${dl_path}" | \ gunzip >"${appdir}/bios.bin" || : ( cd "${appdir}" || err "extract_e6400vga: can't cd ${appdir}" [ -f "bios.bin" ] || err "extract_e6400vga: can't extract bios.bin" "${e6400_unpack}" bios.bin || printf "TODO: fix dell extract util\n" [ -f "${E6400_VGA_romname}" ] || \ err "extract_e6400vga: can't extract vga rom from bios.bin" ) cp "${appdir}"/"${E6400_VGA_romname}" "${_vga_destination}" || \ err "extract_e6400vga: can't copy vga rom to ${_vga_destination}" } # TODO: this code is cancer. hardcoded is bad, and stupid. # TODO: make it *scan* (based on signature, in each file) extract_sch5545ec() { rm -Rf "${dl_path}_extracted" || err "!rm ${dl_path}_extracted" _sch5545ec_destination=${CONFIG_SMSC_SCH5545_EC_FW_FILE#../../} mkdirs "${_sch5545ec_destination}" "extract_sch5545ec" || return 0 # full system ROM (UEFI), to extract with UEFIExtract: _bios="${dl_path}_extracted/Firmware" _bios="${_bios}/1 ${dlsum} -- 1 System BIOS vA.28.bin" # this is the SCH5545 firmware, inside of the extracted UEFI ROM: _sch5545ec_fw="${_bios}.dump/4 7A9354D9-0468-444A-81CE-0BF617D890DF" _sch5545ec_fw="${_sch5545ec_fw}/54 D386BEB8-4B54-4E69-94F5-06091F67E0D3" _sch5545ec_fw="${_sch5545ec_fw}/0 Raw section/body.bin" # <-- this! # this makes the file defined by _sch5545ec_fw available to copy "${uefiextract}" "${_bios}" || \ err "extract_sch5545ec: cannot extract from uefi image" cp "${_sch5545ec_fw}" "${_sch5545ec_destination}" || \ err "extract_sch5545ec: cannot copy sch5545ec firmware file" } mkdirs() { [ -f "${1}" ] && \ printf "mkdirs ${1} ${2}: already downloaded\n" 1>&2 && return 1 mkdir -p "${1%/*}" || err "mkdirs ${1} ${2}: !mkdir ${1%/*}" rm -Rf "${appdir}" || err "mkdirs ${1} ${2}: can't remove ${appdir}" mkdir -p "${appdir}/" || err "mkdirs ${1} ${2}: !mkdir ${appdir}" extract_archive "${dl_path}" "${appdir}" || \ [ "${2}" = "extract_e6400vga" ] || err "mkdirs ${1} ${2}: !extract" } extract_archive() { innoextract "${1}" -d "${2}" || python "${pfs_extract}" "${1}" -e || \ 7z x "${1}" -o"${2}" || unar "${1}" -o "${2}" || \ unzip "${1}" -d "${2}" || return 1 } main $@