diff options
Diffstat (limited to 'resources/scripts/update/blobs/inject')
-rwxr-xr-x | resources/scripts/update/blobs/inject | 398 |
1 files changed, 398 insertions, 0 deletions
diff --git a/resources/scripts/update/blobs/inject b/resources/scripts/update/blobs/inject new file mode 100755 index 00000000..51f67255 --- /dev/null +++ b/resources/scripts/update/blobs/inject @@ -0,0 +1,398 @@ +#!/usr/bin/env bash + +# SPDX-FileCopyrightText: 2022 Caleb La Grange <thonkpeasant@protonmail.com> +# SPDX-FileCopyrightText: 2023 Leah Rowe <info@minifree.org> +# SPDX-License-Identifier: GPL-3.0-only + +sname="" +archive="" +_filetype="" +rom="" +board="" +modifygbe="" +new_mac="" +release="" +releasearchive="" + +cbdir="coreboot/default" +cbcfgsdir="resources/coreboot" +ifdtool="${cbdir}/util/ifdtool/ifdtool" +cbfstool="${cbdir}/util/cbfstool/cbfstool" +nvmutil="util/nvmutil/nvm" +boarddir="" +pciromsdir="pciroms" + +CONFIG_HAVE_MRC="" +CONFIG_HAVE_ME_BIN="" +CONFIG_ME_BIN_PATH="" +CONFIG_KBC1126_FIRMWARE="" +CONFIG_KBC1126_FW1="" +CONFIG_KBC1126_FW1_OFFSET="" +CONFIG_KBC1126_FW2="" +CONFIG_KBC1126_FW2_OFFSET="" +CONFIG_VGA_BIOS_FILE="" +CONFIG_VGA_BIOS_ID="" +CONFIG_GBE_BIN_PATH="" + +main() +{ + sname="${0}" + + if [ $# -lt 1 ]; then + fail "No options specified." + elif [ "${1}" = "listboards" ]; then + listboards + exit 0 + fi + + archive="${1}" + + while getopts r:b:m: option + do + case "${option}" + in + r)rom=${OPTARG};; + b)board=${OPTARG};; + m) + modifygbe=true + new_mac=${OPTARG} + ;; + esac + done + + check_board + build_dependencies + inject_blobs +} + +check_board() +{ + if ! check_release ${archive} ; then + if [ ! -f "${rom}" ]; then + fail "${rom} is not a valid path" + elif [ -z ${rom+x} ]; then + fail 'no rom specified' + elif [ -z ${board+x} ]; then + board=$(detect_board ${rom}) \ + || fail 'no board specified' + fi + else + release=true + releasearchive="${archive}" + board=$(detect_board ${archive}) \ + || fail 'Could not detect board type' + fi + + boarddir="${cbcfgsdir}/${board}" + if [ ! -d "${boarddir}" ]; then + fail "board ${board} not found" + fi +} + +check_release() +{ + if [ ! -f "${archive}" ]; then + return 1 + fi + + if [ "${archive##*.}" = "xz" ]; then + printf "%s\n" "Release archive ${archive} detected" + return 0 + else + return 1 + fi +} + +# This function tries to determine the board from the filename of the rom. +# It will only succeed if the filename is not changed from the build/download +detect_board() +{ + path=${1} + filename=$(basename ${path}) + case ${filename} in + grub_*) + board=$(cut -d '_' -f2-3 <<<${filename}) + ;; + seabios_withgrub_*) + board=$(cut -d '_' -f3-4 <<<${filename}) + ;; + *.tar.xz) + _stripped_prefix=${filename#*_} + board="${_stripped_prefix%.tar.xz}" + ;; + *) + return 1 + esac + + if [ -d "${boarddir}/" ]; then + printf '%s\n' "${board}" + return 0 + else + return 1 + fi +} + +build_dependencies() +{ + if [ ! -d ${cbdir} ]; then + printf "downloading coreboot\n" + ./download coreboot default + fi + + if [ ! -f "${ifdtool}" ]; then + printf "building ifdtool from coreboot\n" + ./build module cbutils default \ + || fail 'could not build ifdtool' + fi + + if [ ! -f "${cbfstool}" ]; then + printf "building cbfstool from coreboot\n" + ./build module cbutils default \ + || fail 'could not build cbfstool' + fi + + ./blobutil download ${board} || \ + fail "Could not download blobs for ${board}" +} + +inject_blobs() +{ + if [ "${release}" = "true" ]; then + echo 'patching release file' + patch_release_roms + else + patch_rom ${rom} + fi +} + +patch_release_roms() +{ + _tmpdir=$(mktemp -d "/tmp/${board}_tmpXXXX") + tar xf "${releasearchive}" -C "${_tmpdir}" || \ + fail 'could not extract release archive' + + for x in ${_tmpdir}/bin/*/*.rom ; do + echo "patching rom $x" + patch_rom ${x} || fail "could not patch ${x}" + done + + ( + cd ${_tmpdir}/bin/* + sha1sum --status -c blobhashes || \ + fail 'ROMs did not match expected hashes' + ) + + if [ "${modifygbe}" = "true" ]; then + for x in ${_tmpdir}/bin/*/*.rom ; do + modify_gbe ${x} + done + fi + + if ! [ -d bin/release ]; then + mkdir -p bin/release + fi + + mv ${_tmpdir}/bin/* bin/release/ && \ + printf '%s\n' 'Success! Your ROMs are in bin/release' + + rm -r "${_tmpdir}" +} + +patch_rom() +{ + rom="${1}" + + set -- "${boarddir}/config/"* + . ${1} 2>/dev/null + . "${boarddir}/board.cfg" + + if [ "$CONFIG_HAVE_MRC" = "y" ]; then + inject_blob_intel_mrc "${rom}" + fi + + if [ "${CONFIG_HAVE_ME_BIN}" = "y" ]; then + inject_blob_intel_me "${rom}" + fi + + if [ "${CONFIG_KBC1126_FIRMWARE}" = "y" ]; then + inject_blob_hp_kbc1126_ec "${rom}" + fi + + if [ "${CONFIG_VGA_BIOS_FILE}" != "" ] \ + && [ "${CONFIG_VGA_BIOS_ID}" != "" ]; then + inject_blob_dell_e6400_vgarom_nvidia + fi + + if [ "${modifygbe}" = "true" ] && ! [ "${release}" = "true" ]; then + modify_gbe ${rom} + fi +} + +inject_blob_intel_mrc() +{ + rom="${1}" + + printf 'adding mrc\n' + + # mrc.bin must be inserted at a specific offset. the only + # libreboot platform that needs it, at present, is haswell + + # in cbfstool, -b values above 0x80000000 are interpreted as + # top-aligned x86 memory locations. this is converted into an + # absolute offset within the flash, and inserted accordingly + # at that offset into the ROM image file + + # coreboot's own build system hardcodes the mrc.bin offset + # because there is only one correct location in memory, but + # it would be useful for lbmk if it could be easily scanned + # from Kconfig, with the option to change it where in practise + # it is not changed + + # the hardcoded offset below is based upon reading of the coreboot + # source code, and it is *always* correct for haswell platform. + # TODO: this logic should be tweaked to handle more platforms + + ${cbfstool} ${rom} add -f mrc/haswell/mrc.bin -n mrc.bin -t mrc \ + -b 0xfffa0000 || exit 1 +} + +inject_blob_intel_me() +{ + printf 'adding intel management engine\n' + + rom="${1}" + + if [ -z ${CONFIG_ME_BIN_PATH} ]; then + fail "CONFIG_ME_BIN_PATH not set" + fi + + _me_location=${CONFIG_ME_BIN_PATH#../../} + + if [ ! -f "${_me_location}" ]; then + fail "CONFIG_ME_BIN_PATH points to missing file" + fi + + ${ifdtool} -i me:${_me_location} ${rom} -O ${rom} || exit 1 +} + +inject_blob_hp_kbc1126_ec() +{ + rom="${1}" + + _ec1_location="${CONFIG_KBC1126_FW1#../../}" + _ec1_offset="${CONFIG_KBC1126_FW1_OFFSET}" + _ec2_location="${CONFIG_KBC1126_FW2#../../}" + _ec2_offset="${CONFIG_KBC1126_FW2_OFFSET}" + + printf "adding hp kbc1126 ec firmware\n" + + if [ "${_ec1_offset}" = "" ] || [ "${_ec1_offset}" = "" ]; then + printf "EC offsets not declared for board: %s\n" \ + "${board}" + exit 1 + fi + if [ "${_ec1_location}" = "" ] || [ "${_ec2_location}" = "" ]; then + printf "EC firmware path not declared for board: %s\n" \ + "${board}" + fi + if [ ! -f "${_ec1_location}" ] || [ ! -f "${_ec2_location}" ]; then + printf "EC firmware not downloaded for board: %s\n" \ + "${board}" + exit 1 + fi + + ${cbfstool} "${rom}" add -f ${_ec1_location} -n ecfw1.bin \ + -b ${_ec1_offset} -t raw || exit 1 + ${cbfstool} "${rom}" add -f ${_ec2_location} -n ecfw2.bin \ + -b ${_ec2_offset} -t raw || exit 1 +} + +inject_blob_dell_e6400_vgarom_nvidia() +{ + rom="${1}" + + _vga_location="${CONFIG_VGA_BIOS_FILE#../../}" + _vga_dir="${_vga_location%/*}" + _vga_filename="${_vga_location##*/}" + + printf "adding pci option rom\n" + + if [ "${_vga_dir}" != "${pciromsdir}" ]; then + printf "Invalid PCI ROM directory: %s\n" ${_vga_dir} + exit 1 + fi + if [ ! -f "${_vga_location}" ]; then + printf "No such file exists: %s\n" ${_vga_location} + exit 1 + fi + + ${cbfstool} ${rom} add -f "${_vga_location}" \ + -n "pci${CONFIG_VGA_BIOS_ID}.rom" \ + -t optionrom || exit 1 +} + +modify_gbe() +{ + printf "changing mac address in gbe to ${new_mac}\n" + + rom=${1} + + if [ -z ${CONFIG_GBE_BIN_PATH} ]; then + fail "CONFIG_GBE_BIN_PATH not set" + fi + + _gbe_location=${CONFIG_GBE_BIN_PATH#../../} + + if [ ! -f "${_gbe_location}" ]; then + fail "CONFIG_GBE_BIN_PATH points to missing file" + fi + + if [ ! -f ${nvmutil} ]; then + make -C util/nvmutil || fail 'failed to build nvmutil' + fi + + _gbe_tmp=$(mktemp -t gbeXXXX.bin) + cp ${_gbe_location} ${_gbe_tmp} + ${nvmutil} "${_gbe_tmp}" setmac ${new_mac} \ + || fail 'failed to modify mac address' + + ${ifdtool} -i GbE:${_gbe_tmp} "${rom}" \ + -O "${rom}" || exit 1 + + rm -f ${_gbe_tmp} +} + +listboards() +{ + for boarddir in ${cbcfgsdir}/*; do + if [ ! -d "${boarddir}" ]; then continue; fi + board="${boarddir##${cbcfgsdir}/}" + board="${board%/}" + printf '%s\n' "${board##*/}" + done +} + +fail() +{ + if [ ! -z ${@+x} ]; then + printf "\n%s: ERROR: ${@}\n" ${sname} + fi + + usage + exit 1 +} + +usage() +{ + cat <<- EOF + USAGE: ./blobutil inject -r [rom path] -b [boardname] -m [macaddress] + Example: ./blobutil inject -r x230_12mb.rom -b x230_12mb + + Adding a macadress to the gbe is optional. + If the [-m] parameter is left blank, the gbe will not be touched. + + Type './blobutil inject listboards' to get a list of valid boards + EOF +} + +main $@ |