From eb23cd3de8cc32d1933dbd94e9eef1c41a5dc153 Mon Sep 17 00:00:00 2001 From: Leah Rowe Date: Sun, 13 Sep 2026 15:33:21 +0100 Subject: split up include/ Signed-off-by: Leah Rowe --- include/common.sh | 14 +- include/env/get.sh | 292 +++++++++++++++++++++++ include/env/init.sh | 398 ++++++++++++++++++++++++++++++++ include/fw/inject.sh | 205 ++++++++++++++++ include/fw/mrc.sh | 69 ++++++ include/fw/rom.sh | 459 ++++++++++++++++++++++++++++++++++++ include/fw/vendor.sh | 624 +++++++++++++++++++++++++++++++++++++++++++++++++ include/get.sh | 292 ----------------------- include/init.sh | 398 -------------------------------- include/inject.sh | 205 ---------------- include/mk/release.sh | 115 +++++++++ include/mk/tree.sh | 628 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/mrc.sh | 69 ------ include/release.sh | 115 --------- include/rom.sh | 459 ------------------------------------ include/tree.sh | 628 -------------------------------------------------- include/vendor.sh | 624 ------------------------------------------------- 17 files changed, 2797 insertions(+), 2797 deletions(-) create mode 100644 include/env/get.sh create mode 100644 include/env/init.sh create mode 100644 include/fw/inject.sh create mode 100644 include/fw/mrc.sh create mode 100644 include/fw/rom.sh create mode 100644 include/fw/vendor.sh delete mode 100644 include/get.sh delete mode 100644 include/init.sh delete mode 100644 include/inject.sh create mode 100644 include/mk/release.sh create mode 100644 include/mk/tree.sh delete mode 100644 include/mrc.sh delete mode 100644 include/release.sh delete mode 100644 include/rom.sh delete mode 100644 include/tree.sh delete mode 100644 include/vendor.sh (limited to 'include') diff --git a/include/common.sh b/include/common.sh index a8f3435f..7ace6ec7 100644 --- a/include/common.sh +++ b/include/common.sh @@ -1,13 +1,13 @@ # SPDX-License-Identifier: GPL-3.0-or-later . "include/lib.sh" -. "include/init.sh" -. "include/vendor.sh" -. "include/mrc.sh" -. "include/inject.sh" -. "include/rom.sh" -. "include/release.sh" -. "include/get.sh" +. "include/env/init.sh" +. "include/fw/vendor.sh" +. "include/fw/mrc.sh" +. "include/fw/inject.sh" +. "include/fw/rom.sh" +. "include/mk/release.sh" +. "include/env/get.sh" xbcommands=" \ version \ diff --git a/include/env/get.sh b/include/env/get.sh new file mode 100644 index 00000000..2a9d182b --- /dev/null +++ b/include/env/get.sh @@ -0,0 +1,292 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +# Copyright (c) 2020-2021,2023-2026 Leah Rowe +# Copyright (c) 2022 Caleb La Grange + +eval "`newvar url bkup_url depend loc subcurl subcurl_bkup subgit subgit_bkup \ + subhash`" + +tmpgit="$xbtmp/gitclone" +tmpgitcache="$xbtmp/tmpgit" + +fetch_targets() +{ + [ -d "src/$project/$tree" ] && \ + return 0 + + git_prep "$url" "$bkup_url" "$xbmkpwd/$configdir/$tree/patches" \ + "src/$project/$tree" "submod" +} + +fetch_project() +{ + xgcctree="" + + . "config/git/$project/pkg.cfg" || \ + err "Can't read config 'config/git/$project/pkg.cfg'" \ + "fetch_project" "@" + + if [ -z "$url" ] || [ -z "$bkup_url" ]; then + err "url/bkup_url not both set 'config/git/$project/pkg.cfg'" \ + "fetch_project" "$@" + fi + + [ -n "$xgcctree" ] && \ + x_ ./mk -f coreboot "$xgcctree" + + [ -n "$depend" ] && \ + for d in $depend ; do + x_ ./mk -f $d + done + + clone_project +} + +clone_project() +{ + singletree "$project" || \ + return 0 + + loc="src/$project" + [ -d "$loc" ] && \ + return 0 + + remkdir "${tmpgit%/*}" + git_prep "$url" "$bkup_url" "$xbmkpwd/config/$project/patches" "$loc" +} + +git_prep() +{ + printf "Creating code directory, src/%s/%s\n" "$project" "$tree" + + _patchdir="$3" + _loc="$4" # $1 and $2 are gitrepo and gitrepo_backup + + [ -z "$rev" ] && \ + err "$project/$tree: rev not set" "git_prep" "$@" + + xbget git "$1" "$2" "$tmpgit" "$rev" "$_patchdir" + if singletree "$project" || [ $# -gt 4 ]; then + dx_ fetch_submodule "$mdir/module.list" + fi + + [ "$_loc" != "${_loc%/*}" ] && \ + x_ mkdir -p "${_loc%/*}" + + x_ mv "$tmpgit" "$_loc" +} + +fetch_submodule() +{ + mcfgdir="$mdir/${1##*/}" + eval "`newvar st subcurl subcurl_bkup subgit subgit_bkup subhash`" + + if e "$mcfgdir/module.cfg" f missing; then + return 0 + fi + . "$mcfgdir/module.cfg" || \ + err "Can't read '$mcfgdir/module.cfg'" "fetch_submodules" "$@" + + [ -n "$subgit" ] && [ -n "$subgit_bkup" ] && \ + st="git" + [ -n "$subcurl" ] && [ -n "$subcurl_bkup" ] && \ + st="curl$st" + [ "$st" = "curlgit" ] && \ + err "$mdir: git+curl defined" "fetch_submodule" "$@" + [ -z "$st" ] && \ + return 0 + [ -z "$subhash" ] && \ + err "subhash not set" "fetch_submodule" "$@" + + [ "$st" = "git" ] && \ + x_ rm -Rf "$tmpgit/$1" + + eval "xbget \"\$st\" \"\$sub$st\" \"\$sub${st}_bkup\" \"\$tmpgit/\$1\" \ + \"\$subhash\" \"\$mdir/\${1##*/}/patches\"" +} + +# TODO: in the following functions, argument numbers are used +# which is hard to understand. the code should be modified +# so that variable names are used instead, for easy reading + +xbget() +{ + [ "$1" != "curl" ] && [ "$1" != "copy" ] && [ "$1" != "git" ] && \ + err "Bad dlop (arg 1)" "xbget" "$@" + + for url in "$2" "$3"; do + [ -z "$url" ] && \ + err "empty URL given in" "xbget" "$@" + try_fetch_$1 "$url" "$@" || \ + continue + [ -e "$4" ] && \ + return 0; : # successful download/copy + done + + err "failed to download file/repository" "xbget" "$@"; : +} + +try_fetch_git() +{ + # 1st argument $1 is the current git remote being tried, + # let's say it was https://foo.example.com/repo, then cached + # directories becomes cache/mirror/foo.example.com/repo + + cached="clone" + [ "$XBMK_CACHE_MIRROR" = "y" ] && \ + cached="mirror" + cached="$cached/${1#*://}" + cached="$XBMK_CACHE/$cached" + + x_ mkdir -p "${5%/*}" "${cached%/*}" + + try_$2 "$cached" "$@" || \ + return 1 + [ ! -d "$cached" ] && \ + return 1 + + if [ ! -d "$5" ]; then + tmpclone "$cached" "$5" "$6" "$7" || \ + err "Can't clone final repo" "try_fetch" "$@"; : + fi + + [ ! -d "$5" ] && \ + return 1; : +} + +try_fetch_copy() +{ + try_fetch_curl "$@" || return 1; : +} + +try_fetch_curl() +{ + cached="file/$6" + cached="$XBMK_CACHE/$cached" + + x_ mkdir -p "${5%/*}" "${cached%/*}" + + if bad_checksum "$6" "$cached" 2>/dev/null; then + x_ rm -f "$cached" + fi + + [ -f "$cached" ] || \ + try_$2 "$cached" "$@" || \ + return 1 + + [ -f "$5" ] && \ + if bad_checksum "$6" "$5" 2>/dev/null; then + x_ cp "$cached" "$5" + fi + + if [ ! -f "$cached" ]; then + return 1 + elif bad_checksum "$6" "$cached"; then + x_ rm -f "$cached" + return 1 + fi + + [ "$cached" != "$5" ] && \ + x_ cp "$cached" "$5" + + if bad_checksum "$6" "$5"; then + x_ rm -f "$5" + return 1 + elif [ ! -f "$5" ]; then + return 1 + fi +} + +try_curl() +{ + ua="Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0" + + ( x_ curl --location --retry 3 -A "$ua" "$2" -o "$1" ) \ + || ( x_ wget --tries 3 -U "$ua" "$2" -O "$1" ) \ + || return 1; : +} + +try_copy() +{ + ( x_ cp "$2" "$1" ) || return 1; : +} + +try_git() +{ + gitdest="`findpath "$1" || err "Can't get findpath for '$1'"`" || \ + err "failed findpath for '$1'" try_get "$@" + + x_ rm -Rf "$tmpgitcache" + + if [ ! -d "$gitdest" ]; then + if [ "$XBMK_CACHE_MIRROR" = "y" ]; then + ( x_ git clone --mirror "$2" "$tmpgitcache" ) || \ + return 1 + else + ( x_ git clone "$2" "$tmpgitcache" ) || return 1 + fi + + x_ mkdir -p "${gitdest%/*}" + x_ mv "$tmpgitcache" "$gitdest" + fi + + if git -C "$gitdest" show "$7" 1>/dev/null 2>/dev/null && \ + [ "$forcepull" != "y" ]; then + # don't try to pull the latest changes if the given target + # revision already exists locally. this saves a lot of time + # during release builds, and reduces the chance that we will + # interact with grub.git or gnulib.git overall during runtime + + return 0 + fi + + if [ "$XBMK_CACHE_MIRROR" = "y" ]; then + ( x_ git -C "$gitdest" fetch ) || :; : + ( x_ git -C "$gitdest" update-server-info ) || :; : + else + ( x_ git -C "$gitdest" pull --all ) || :; : + fi +} + +bad_checksum() +{ + if e "$2" f missing; then + return 0 + fi + + build_sbase + csum="$(x_ "$sha512sum" "$2" | awk '{print $1}')" || \ + err "!sha512 '$2' $1" bad_checksum "$@" + + [ "$csum" = "$1" ] && \ + return 1 + + x_ rm -f "$2" + printf "BAD SHA512 %s, '%s'; need %s\n" "$csum" "$2" "$1" 1>&2 +} + +tmpclone() +{ + ( x_ git clone "$1" "$2" ) || return 1 + ( x_ git -C "$2" reset --hard "$3" ) || return 1 + + [ ! -d "$4" ] && \ + return 0 + + tmpclone_patchlist="`mktemp || err "Can't create tmp patch list"`" || \ + err "Can't create tmp patch list" "tmpclone" "$@" + + x_ find "$4" -type f | sort > "$tmpclone_patchlist" || \ + err "Can't write patch names to '$tmpclone_patchlist'" \ + "tmpclone" "$@" + + while read -r tmpclone_patch; do + + ( x_ git -C "$2" am -3 --keep-cr "$tmpclone_patch" ) || \ + err "Can't apply '$tmpclone_patch'" "tmpclone" "$@"; : + + done < "$tmpclone_patchlist" || \ + err "Can't read '$tmpclone_patchlist'" "tmpclone" "$@" + + x_ rm -f "$tmpclone_patchlist" +} diff --git a/include/env/init.sh b/include/env/init.sh new file mode 100644 index 00000000..9adeee60 --- /dev/null +++ b/include/env/init.sh @@ -0,0 +1,398 @@ +# SPDX-License-Identifier: GPL-3.0-only + +# Copyright (c) 2022 Caleb La Grange +# Copyright (c) 2022 Ferass El Hafidi +# Copyright (c) 2020-2026 Leah Rowe +# Copyright (c) 2025 Alper Nebi Yasak + +projectname="libreboot" +projectsite="https://libreboot.org/" + +sha512sum="util/sbase/sha512sum" + +eval "`newvar aur_notice basetmp board checkvarschk checkvarsxbmk configdir \ + datadir is_child python pyver reinstall relname version versiondate \ + xbmklock xbmkpath xbmkpwd xbmkpwd xbtmp`" + +xbmk_init() +{ + xbmkpwd="`pwd || err "Cannot generate PWD"`" || err "!" xbmk_init "$@" + xbmklock="$xbmkpwd/lock" + basetmp="$xbmkpwd/xbmkwd" + sha512sum="$xbmkpwd/util/sbase/sha512sum" + + if [ $# -gt 0 ] && [ "$1" = "dependencies" ]; then + x_ xbmkpkg "$@" + exit 0 + fi + + id -u 1>/dev/null 2>/dev/null || \ + err "suid check failed" "xbmk_init" "$@" + + [ "$(id -u)" = "0" ] && \ + err "this command as root is not permitted" "xbmk_init" "$@" + + export PWD="$xbmkpwd" + x_ mkdir -p "$basetmp" "cache" + + for init_cmd in get_version set_env set_threads git_init child_exec; do + xbmk_$init_cmd "$@" || \ + break; : + done +} + +xbmkpkg() +{ + xchk xbmkpkg "$@" + + [ $# -gt 2 ] && \ + reinstall="$3" + + . "config/dependencies/$2" || \ + err "Can't read 'config/dependencies/$2'" "xbmkpkg" "$@" + + if [ -z "$pkg_add" ] || [ -z "$pkglist" ]; then + err "pkg_add/pkglist not both set" "xbmkpkg" "$@" + fi + + if [ "$2" == "gentoo" ]; then + + if [ -z "$pkg_use" ] || [ -z "$pkg_use_file" ]; then + err "pkg_use/pkg_use_file not both set" "xbmkpkg" "$@" + fi + + printf "Updating package use...\n" + printf "Writing into %s" "$pkg_use_file..." + + x_ mkdir -p "`dirname $pkg_use_file`" + + printf "%s\n" "$pkg_use" >> "$pkg_use_file" + fi + + x_ $pkg_add $pkglist + + [ -n "$aur_notice" ] && \ + printf "You need AUR packages: %s\n" "$aur_notice" 1>&2; : +} + +xbmk_get_version() +{ + [ ! -f ".version" ] || \ + read -r version < ".version" || \ + err "can't read version file" "xbmk_get_version" "$@" + [ ! -f ".versiondate" ] || \ + read -r versiondate < ".versiondate" || \ + err "can't read versiondate" xbmk_get_version "$@" + + [ -f ".version" ] && [ -z "$version" ] && \ + err "version not set" "xbmk_get_version" "$@" + [ -f ".versiondate" ] && [ -z "$versiondate" ] && \ + err "versiondate not set" "xbmk_get_version" "$@" + + [ ! -e ".git" ] && [ ! -f ".version" ] && \ + version="unknown" + [ ! -e ".git" ] && [ ! -f ".versiondate" ] && \ + versiondate="1716415872" + + xbmk_sanitize_version + + [ -n "$version" ] && \ + relname="$projectname-$version"; : +} + +# a parent instance will cause this function to return 0. +# a child instance will return 1, skipping further initialisation +# after this function is called. +xbmk_set_env() +{ + is_child="n" + xbmkpath="$PATH" + + # unify all temporary files/directories in a single TMPDIR + [ -n "${TMPDIR+x}" ] && [ "${TMPDIR%_*}" != "$basetmp/xbmk" ] && \ + unset TMPDIR + if [ -n "${TMPDIR+x}" ]; then + export TMPDIR="$TMPDIR" + xbtmp="$TMPDIR" + fi + [ -n "${TMPDIR+x}" ] && \ + is_child="y" + + if [ "$is_child" = "y" ]; then + xbmk_child_set_env + return 1 # child instance. discontinue initialisation. + fi + xbmk_parent_set_env +} + +xbmk_child_set_env() +{ + xbmk_child_set_tmp + + [ -z "${XBMK_CACHE+x}" ] && \ + err "XBMK_CACHE unset on child" "xbmk_set_env" "$@" + [ -z "${XBMK_THREADS+x}" ] && \ + xbmk_set_threads + [ -z "${XBMK_CACHE_MIRROR+x}" ] && \ + xbmk_set_mirror; : +} + +xbmk_child_set_tmp() +{ + eval "`newvar badtmp locktmp xbtmpchk`" + + xbtmpchk="`findpath "$TMPDIR" || err "!findpath $TMPDIR"`" || \ + err "!findpath '$TMPDIR'" "xbmk_child_set_tmp" "$@" + + read -r locktmp < "$xbmklock" || \ + err "can't read '$xbmklock'" "xbmk_child_set_tmp" "$@" + + if [ "$locktmp" != "$xbtmpchk" ]; then + badtmp="TMPDIR '$xbtmpchk' changed; was '$locktmp'" + printf "bad TMPDIR init, '%s': %s\n" "$TMPDIR" "$badtmp" 1>&2 + err "'$xbmklock' present with bad tmpdir. is a build running?" + fi + + xbtmp="$xbtmpchk" + export TMPDIR="$xbtmpchk" +} + +xbmk_parent_set_env() +{ + xbmk_parent_check_tmp + + printf "%s\n" "$xbtmp" > "$xbmklock" || \ + err "cannot create '$xbmklock'" xbmk_set_env "$@"; : + + # not really critical for security, but it's a barrier + # against the user to make them think twice before deleting it + # in case an actual instance of xbmk is already running: + + x_ chmod -w "$xbmklock" + + xbmk_parent_set_export + xbmk_set_version + + remkdir "$xbtmp" "$xbtmp/gnupath" "$xbtmp/xbmkpath" + + xbmk_set_pyver + xbmk_set_mirror +} + +xbmk_parent_check_tmp() +{ + export TMPDIR="$basetmp" + + xbmklist="`mktemp || err "can't make tmplist"`" || \ + err "can't make tmplist" xbmk_parent_check_tmp "$@" + + x_ rm -f "$xbmklist" + x_ touch "$xbmklist" + + for xtmpdir in "$basetmp"/xbmk_*; do + if [ -e "$xtmpdir" ]; then + printf "%s\n" "$xtmpdir" >> "$xbmklist" || \ + err "can't write '$xtmpdir' to '$xbmklist'" \ + "xbmk_parent_check_tmp" "$@"; : + fi + done + + # set up a unified temporary directory, for common deletion later: + export TMPDIR="`x_ mktemp -d -t xbmk_XXXXXXXX`" || \ + err "can't export TMPDIR" "xbmk_parent_check_tmp" "$@" + xbtmp="$TMPDIR" + + while read -r xtmpdir; do + [ "$xtmpdir" = "$xbtmp" ] && \ + err "pre-existing $xbtmp" xbmk_parent_check_tmp "$@"; : + done < "$xbmklist" || \ + err "Can't read xbmklist: '$xbmklist'" "xbmk_parent_check_tmp" "$@" + + x_ rm -f "$xbmklist" +} + +xbmk_parent_set_export() +{ + export XBMK_CACHE="$xbmkpwd/cache" + + [ -e "$XBMK_CACHE" ] && [ ! -d "$XBMK_CACHE" ] && \ + err "cachedir '$XBMK_CACHE' is a file" \ + "xbmk_parent_set_export" "$@" + + export PATH="$xbtmp/xbmkpath:$xbtmp/gnupath:$PATH" + xbmkpath="$PATH" + + # if "y": a coreboot target won't be built if target.cfg says release=n + # (this is used to exclude certain build targets from releases) + + [ -z "${XBMK_RELEASE+x}" ] && \ + export XBMK_RELEASE="n" + [ "$XBMK_RELEASE" = "Y" ] && \ + export XBMK_RELEASE="y" + [ "$XBMK_RELEASE" != "y" ] && \ + export XBMK_RELEASE="n"; : +} + +xbmk_set_threads() +{ + [ -z "${XBMK_THREADS+x}" ] && \ + export XBMK_THREADS=1 + expr "X$XBMK_THREADS" : "X-\{0,1\}[0123456789][0123456789]*$" \ + 1>/dev/null 2>/dev/null || \ + export XBMK_THREADS=1; : +} + +xbmk_set_version() +{ + version_="$version" + [ ! -e ".git" ] || \ + version="$(git describe --tags HEAD 2>&1)" || \ + version="git-$(git rev-parse HEAD 2>&1)" || \ + version="$version_" + + versiondate_="$versiondate" + [ ! -e ".git" ] || \ + versiondate="$(git show --no-patch --no-notes \ + --pretty='%ct' HEAD)" || versiondate="$versiondate_" + + update_xbmkver "." + + relname="$projectname-$version" + export LOCALVERSION="-$projectname-${version%%-*}" +} + +xbmk_set_pyver() +{ + python="python3" + pyver="2" + pyv="import sys; print(sys.version_info[:])" + + pybin python3 1>/dev/null || \ + python="python" + [ "$python" = "python3" ] && \ + pyver="3" + pybin "$python" 1>/dev/null || \ + pyver="" + + [ -z "$pyver" ] || \ + "`x_ pybin "$python"`" -c "$pyv" 1>/dev/null \ + 2>/dev/null || \ + err "Can't detect Python version." "xbmk_set_pyver" "$@" + if [ -n "$pyver" ]; then + pyver="$("$(pybin "$python")" -c "$pyv" | awk '{print $1}')" + pyver="${pyver#(}" + pyver="${pyver%,}" + fi + [ "${pyver%%.*}" != "3" ] && \ + err "Bad python version (must by 3.x)" "xbmk_set_pyver" "$@" + + # set up python in PATH (environmental variable): + ( + x_ cd "$xbtmp/xbmkpath" + x_ ln -s "`x_ pybin "$python"`" python || \ + err "can't make symlink" "xbmk_set_pyver" "$@" + + ) || err "Can't link Python in $xbtmp/xbmkpath" xbmk_set_pyver "$@"; : +} + +# Use direct path, to prevent a hang if Python is using a virtual environment, +# not command -v, to prevent a hang when checking python's version +# See: https://docs.python.org/3/library/venv.html#how-venvs-work +pybin() +{ + py="import sys; quit(1) if sys.prefix == sys.base_prefix else quit(0)" + + venv=1 + command -v "$1" 1>/dev/null 2>/dev/null || \ + venv=0 + + [ $venv -lt 1 ] || \ + "$1" -c "$py" 1>/dev/null 2>/dev/null || \ + venv=0 + + # try the direct path from PATH first. the binary specified by venv + # can be called directly, which then removes use of the venv + if [ $venv -gt 0 ] && [ -L "`command -v "$1" 2>/dev/null`" ]; then + pypath="$(findpath \ + "$(command -v "$1" 2>/dev/null)" 2>/dev/null || :)" + if [ -e "$pypath" ] && [ ! -d "$pypath" ] && \ + [ -x "$pypath" ]; then + printf "%s\n" "$pypath" + return 0 + fi + fi + + # if python venv: fall back to common PATH directories for checking: + [ $venv -gt 0 ] && for pypath in "/usr/local/bin" "/usr/bin"; do + if [ -e "$pypath/$1" ] && [ ! -d "$pypath/$1" ] && \ + [ -x "$pypath/$1" ]; then + printf "%s/%s\n" "$pypath" "$1" + return 0 + fi + done && return 1 + + # Defer to normal command -v if not a venv + command -v "$1" 2>/dev/null || \ + return 1; : +} + +xbmk_set_mirror() +{ + # defines whether cache/clone/ (regular clones) + # or cache/mirror (--mirror clones) are used, per project + + # to use cache/mirror/ do: export XBMK_CACHE_MIRROR="y" + # mirror/ stores a separate directory per repository, even per backup. + # it's slower, and uses more disk space, and some upstreams might not + # appreciate it, so it should only be used for development or archival + + [ -z "${XBMK_CACHE_MIRROR+x}" ] && \ + export XBMK_CACHE_MIRROR="n" + [ "$XBMK_CACHE_MIRROR" != "y" ] && \ + export XBMK_CACHE_MIRROR="n"; : +} + +xbmk_git_init() +{ + # the git identity check is only needed for: ./mk -b coreboot [args] + [ "${2-}" = "-b" ] && [ "${3-}" = "coreboot" ] && \ + for gitarg in "user.name" "user.email"; do + git config --includes $gitarg 1>/dev/null 2>/dev/null || \ + err "Run this first: $gitcmd \"your ${gitcmd##*.}\"" \ + "xbmk_git_init" "$@"; : + done + + [ -L ".git" ] && \ + err "'$xbmkpwd/.git' is a symlink" "xbmk_git_init" "$@" + [ -e ".git" ] && \ + return 0 + + ( + export GIT_COMMITTER_DATE="@$versiondate +0000" + export GIT_AUTHOR_DATE="@$versiondate +0000" + + x_ git init 1>/dev/null 2>/dev/null + x_ git add -A . 1>/dev/null 2>/dev/null + x_ git -c user.name="xbmk" -c user.email="xbmk@example.com" \ + commit -m "$projectname $version" \ + --author="xbmk " 1>/dev/null 2>/dev/null + x_ git -c user.name="xbmk" -c user.email="xbmk@example.com" \ + tag -a "$version" -m "$projectname $version" \ + 1>/dev/null 2>/dev/null; : + + ) || err "Can't initialise workdir" xbmk_git_init "$@"; : +} + +xbmk_child_exec() +{ + xbmk_rval=0 + + ( x_ ./mk "$@" ) || xbmk_rval=1 + + ( x_ rm -Rf "$xbtmp" ) || xbmk_rval=1 + ( x_ rm -f "$xbmklock" ) || xbmk_rval=1 + + exit $xbmk_rval +} + +xbmk_init "$@" diff --git a/include/fw/inject.sh b/include/fw/inject.sh new file mode 100644 index 00000000..0760c1d8 --- /dev/null +++ b/include/fw/inject.sh @@ -0,0 +1,205 @@ +# SPDX-License-Identifier: GPL-3.0-only + +# Copyright (c) 2022 Caleb La Grange +# Copyright (c) 2022 Ferass El Hafidi +# Copyright (c) 2023-2026 Leah Rowe + +cbcfgsdir="config/coreboot" +tmpromdel="$XBMK_CACHE/DO_NOT_FLASH" +nvmutil="util/nvmutil/nvmutil" +ifdtool="elf/coreboot/default/ifdtool" + +checkvars="CONFIG_GBE_BIN_PATH ${checkvarsxbmk-} ${checkvarschk-}" + +eval "`newvar archive board boarddir IFD_platform ifdprefix \ + new_mac tmpromdir tree xchanged $checkvars`" + +inject() +{ + remkdir "$tmpromdel" + + [ $# -lt 1 ] && \ + err "No options specified" "inject" "$@" + + archive="$1"; + new_mac="xx:xx:xx:xx:xx:xx" + + nuke="" + xchanged="" + + [ $# -gt 1 ] && case "$2" in + nuke) + new_mac="" + nuke="nuke" + ;; + setmac) + if [ $# -gt 2 ]; then + new_mac="$3" && \ + [ -z "$new_mac" ] && \ + err "Empty MAC address" "inject" "$@"; : + fi + ;; + *) + err "Unrecognised inject mode: '$2'" "inject" "$@" ;; + esac + + [ "$new_mac" = "keep" ] && \ + new_mac="" + + check_release + if check_target; then + patch_release || \ + return 0; : + fi + [ "$xchanged" = "y" ] && \ + remktar + + if [ "$xchanged" = "y" ]; then + printf "\n'%s' was modified\n" "$archive" 1>&2 + else + printf "\n'%s' was NOT modified\n" "$archive" 1>&2 + fi + + x_ rm -Rf "$tmpromdel" +} + +check_release() +{ + [ -L "$archive" ] && \ + err "'$archive' is a symlink" "check_release" "$@" + if e "$archive" f missing; then + err "'$archive' missing" "check_release" "$@" + fi + + archivename="`basename "$archive" || err "Can't get '$archive' name"`" \ + || err "can't get '$archive' name" "check_release" "$@" + + [ -z "$archivename" ] && \ + err "Can't determine archive name" "check_release" "$@" + + case "$archivename" in + *_src.tar.xz) + err "'$archive' is a src archive!" "check_release" "$@" + ;; + grub_*|seagrub_*|custom_*|seauboot_*|seabios_withgrub_*) + err "'$archive' is a ROM image" "check_release" "$@" + ;; + *.tar.xz) _stripped_prefix="${archivename#*_}" + board="${_stripped_prefix%.tar.xz}" + ;; + *) + err "'$archive': cannot detect board" "check_release" "$@" + ;; + esac; : +} + +check_target() +{ + [ "$board" != "${board#serprog_}" ] && \ + return 1 + + boarddir="$cbcfgsdir/$board" + + . "$boarddir/target.cfg" || \ + err "Can't read '$boarddir/target.cfg'" "check_target" "$@" + + [ -z "$tree" ] && \ + err "tree unset in '$boarddir/target.cfg'" "check_target" "$@" + + x_ ./mk -d coreboot "$tree" + + ifdtool="elf/coreboot/$tree/ifdtool" + + [ -n "$IFD_platform" ] && \ + ifdprefix="-p $IFD_platform"; : +} + +patch_release() +{ + [ "$nuke" != "nuke" ] && \ + x_ ./mk download "$board" + + has_hashes="n" + tmpromdir="$tmpromdel/bin/$board" + + remkdir "${tmpromdir%"/bin/$board"}" + x_ tar -xf "$archive" -C "${tmpromdir%"/bin/$board"}" + + for _hashes in "vendorhashes" "blobhashes"; do + if e "$tmpromdir/$_hashes" f; then + has_hashes="y" + hashfile="$_hashes" + + break + fi + done + + readkconfig || \ + return 1 + + [ -n "$new_mac" ] && [ -n "$CONFIG_GBE_BIN_PATH" ] && \ + modify_mac; : +} + +readkconfig() +{ + x_ rm -f "$xbtmp/cbcfg" + fx_ scankconfig x_ find "$boarddir/config" -type f + + if e "$xbtmp/cbcfg" f missing; then + return 1 + fi + + . "$xbtmp/cbcfg" || \ + err "Can't read '$xbtmp/cbcfg'" "readkconfig" "$@" + + setvfile "$@" || \ + return 1; : +} + +scankconfig() +{ + for cbc in $checkvars; do + grep "$cbc" "$1" 2>/dev/null 1>>"$xbtmp/cbcfg" || : + done +} + +modify_mac() +{ + x_ cp "${CONFIG_GBE_BIN_PATH##*../}" "$xbtmp/gbe" + + if [ -n "$new_mac" ] && [ "$new_mac" != "restore" ]; then + x_ make -C util/nvmutil clean + x_ make -C util/nvmutil + + x_ "$nvmutil" "$xbtmp/gbe" setmac "$new_mac" + fi + + fx_ newmac x_ find "$tmpromdir" -maxdepth 1 -type f -name "*.rom" + + printf "\nThe following GbE NVM data will be written:\n" + x_ "$nvmutil" "$xbtmp/gbe" dump | grep -v "bytes read from file" || : +} + +newmac() +{ + if e "$1" f; then + xchanged="y" + x_ "$ifdtool" $ifdprefix -i GbE:"$xbtmp/gbe" "$1" -O "$1" + fi +} + +remktar() +{ + ( + x_ cd "${tmpromdir%"/bin/$board"}" + + printf "Re-building tar archive (please wait)\n" + mkrom_tarball "bin/$board" 1>/dev/null + + ) || err "Cannot re-generate '$archive'" "remktar" "$@" + + mv "${tmpromdir%"/bin/$board"}/bin/${relname}_${board}.tar.xz" \ + "$archive" || \ + err "'$archive' -> Can't overwrite" "remktar" "$@"; : +} diff --git a/include/fw/mrc.sh b/include/fw/mrc.sh new file mode 100644 index 00000000..10d7e437 --- /dev/null +++ b/include/fw/mrc.sh @@ -0,0 +1,69 @@ +# SPDX-License-Identifier: GPL-2.0-only + +# Logic based on util/chromeos/crosfirmware.sh in coreboot cfc26ce278. +# Modifications in this version are Copyright 2021,2023-2025 Leah Rowe. +# Original copyright detailed in repo: https://review.coreboot.org/coreboot/ + +eval "`newvar MRC_board MRC_hash MRC_url MRC_url_bkup SHELLBALL`" + +extract_refcode() +{ + extract_mrc + + # cbfstool after coreboot 4.13 changed the stage file attribute scheme, + # and refcode is extracted from an image using the old scheme. we use + # cbfstool from coreboot 4.11_branch, the tree used by ASUS KGPE-D16: + + [ -z "$cbfstoolref" ] && \ + err "cbfstoolref not set" "extract_refcode" "$@" + + x_ mkdir -p "${_pre_dest%/*}" + + x_ "$cbfstoolref" "$appdir/bios.bin" extract \ + -m x86 -n fallback/refcode -f "$appdir/ref" -r RO_SECTION + + # enable the Intel GbE device, if told by offset MRC_refcode_gbe + [ -n "$MRC_refcode_gbe" ] && \ + x_ dd if="config/ifd/hp820g2/1.bin" of="$appdir/ref" bs=1 \ + seek=$MRC_refcode_gbe count=1 conv=notrunc; : + + x_ mv "$appdir/ref" "$_pre_dest" +} + +extract_mrc() +{ + [ -z "$MRC_board" ] && \ + err "MRC_board unset" "extract_mrc" "$@" + [ -z "$CONFIG_MRC_FILE" ] && \ + err "CONFIG_MRC_FILE unset" "extract_mrc" "$@" + + SHELLBALL="chromeos-firmwareupdate-$MRC_board" + + ( + x_ cd "$appdir" + extract_partition "${MRC_url##*/}" + extract_archive "$SHELLBALL" . + + ) || err "mrc download/extract failure" "extract_mrc" "$@" + + x_ "$cbfstool" "$appdir/"bios.bin extract -n mrc.bin \ + -f "${_pre_dest%/*}/mrc.bin" -r RO_SECTION +} + +extract_partition() +{ + printf "Extracting ROOT-A partition\n" + + ROOTP=$( printf "unit\nB\nprint\nquit\n" | \ + parted "${1%.zip}" 2>/dev/null | grep "ROOT-A" ) + + START=$(( $( echo $ROOTP | cut -f2 -d\ | tr -d "B" ) )) + SIZE=$(( $( echo $ROOTP | cut -f4 -d\ | tr -d "B" ) )) + + x_ dd if="${1%.zip}" of="root-a.ext2" bs=1024 \ + skip=$(( $START / 1024 )) count=$(( $SIZE / 1024 )) + + printf "cd /usr/sbin\ndump chromeos-firmwareupdate %s\nquit" \ + "$SHELLBALL" | debugfs "root-a.ext2" || \ + err "!extract shellball" "extract_partition" "$@" +} diff --git a/include/fw/rom.sh b/include/fw/rom.sh new file mode 100644 index 00000000..adaac8a0 --- /dev/null +++ b/include/fw/rom.sh @@ -0,0 +1,459 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +# Copyright (c) 2014-2016,2020-2021,2023-2025 Leah Rowe +# Copyright (c) 2021-2022 Ferass El Hafidi +# Copyright (c) 2022 Caleb La Grange +# Copyright (c) 2022-2023 Alper Nebi Yasak +# Copyright (c) 2023-2024 Riku Viitanen + +grubdata="config/data/grub" + +buildser() +{ + if [ "$1" = "pico" ]; then + x_ cmake -DPICO_BOARD="$2" \ + -DPICO_SDK_PATH="$picosdk" -B "$sersrc/build" "$sersrc" + x_ cmake --build "$sersrc/build" + elif [ "$1" = "stm32" ]; then + x_ make -C "$sersrc" libopencm3-just-make BOARD=$2 + x_ make -C "$sersrc" BOARD=$2 + fi + + x_ mkdir -p "bin/serprog_$1" + x_ mv "$serx" "bin/serprog_$1/serprog_$2.${serx##*.}" +} + +copyps1bios() +{ + $if_dry_build \ + return 0 + + remkdir "bin/playstation" + x_ cp src/pcsx-redux/src/mips/openbios/openbios.bin bin/playstation + + printf "MIT License\n\nCopyright (c) 2019-2025 PCSX-Redux authors\n\n" \ + > bin/playstation/COPYING.txt || \ + err "can't write PCSX Redux copyright info" "copyps1bios" "$@" + + x_ cat config/snippet/mit >>bin/playstation/COPYING.txt || \ + err "can't copy MIT license snippet" "copyps1bios" "$@" +} + +mkpayload_grub() +{ + eval "`newvar grub_modules grub_install_modules`" + + $if_dry_build \ + return 0 + + . "$grubdata/module/$tree" || \ + err "Can't read '$grubdata/module/$tree'" "mkpayload_grub" "$@" + + x_ rm -f "$srcdir/grub.elf" + + x_ "$srcdir/grub-mkstandalone" \ + --grub-mkimage="$srcdir/grub-mkimage" \ + -O i386-coreboot -o "$srcdir/grub.elf" -d "${srcdir}/grub-core/" \ + --fonts= --themes= --locales= --modules="$grub_modules" \ + --install-modules="$grub_install_modules" \ + "/boot/grub/grub_default.cfg=${srcdir}/.config" \ + "/boot/grub/grub.cfg=$grubdata/memdisk.cfg"; : +} + +corebootpremake() +{ + [ "$XBMK_RELEASE" = "y" ] && [ "$release" = "n" ] && \ + return 0 + + $if_not_dry_build \ + cook_coreboot_config + + fx_ check_coreboot_util printf "cbfstool\nifdtool\n" + + printf "%s\n" "${version%%-*}" > "$srcdir/.coreboot-version" || \ + err "!mk $srcdir .coreboot-version" "corebootpremake" "$@" + + [ -z "$mode" ] && [ "$target" != "$tree" ] && \ + x_ ./mk download "$target"; : +} + +cook_coreboot_config() +{ + if [ -z "$mode" ] && [ -f "$srcdir/.config" ]; then + printf "CONFIG_CCACHE=y\n" >> "$srcdir/.config" || \ + err "can't cook '$srcdir'" "cook_coreboot_config" "$@" + fi +} + +check_coreboot_util() +{ + [ "$badhash" = "y" ] && \ + x_ rm -f "elf/coreboot/$tree/$1" + if e "elf/coreboot/$tree/$1" f; then + return 0 + fi + + utilelfdir="elf/coreboot/$tree" + utilsrcdir="src/coreboot/$tree/util/$1" + + utilmode="" + [ -n "$mode" ] && \ + utilmode="clean" + + x_ make -C "$utilsrcdir" $utilmode -j$XBMK_THREADS $makeargs + + if [ -n "$mode" ]; then + x_ rm -Rf "$utilelfdir" + return 0 + elif [ -n "$mode" ] || [ -f "$utilelfdir/$1" ]; then + return 0 + fi + + x_ mkdir -p "$utilelfdir" + x_ cp "$utilsrcdir/$1" "$utilelfdir" + + [ "$1" = "cbfstool" ] && \ + x_ cp "$utilsrcdir/rmodtool" "$utilelfdir"; : +} + +coreboot_pad_one_byte() +{ + [ "$XBMK_RELEASE" = "y" ] && [ "$release" = "n" ] && \ + return 0 + + $if_not_dry_build \ + pad_one_byte "$srcdir/build/coreboot.rom" +} + +mkcorebootbin() +{ + [ "$XBMK_RELEASE" = "y" ] && [ "$release" = "n" ] && \ + return 0 + + $if_not_dry_build \ + check_coreboot_util cbfstool + + $if_not_dry_build \ + check_coreboot_util ifdtool + + for y in "$target_dir/config"/*; do + defconfig="$y" + mkcorebootbin_real + done + + mkcoreboottar +} + +mkcorebootbin_real() +{ + [ "$target" = "$tree" ] && \ + return 0 + + tmprom="$xbtmp/coreboot.rom" + + initmode="${defconfig##*/}" + displaymode="${initmode##*_}" + if [ "$displaymode" = "$initmode" ]; then + # blank it for "normal" or "fspgop" configs: + + displaymode="" + fi + initmode="${initmode%%_*}" + cbfstool="elf/coreboot/$tree/cbfstool" + + # cbfstool option backends, if they exist + cbfscfg="config/coreboot/$target/cbfs.cfg" + + elfrom="elf/coreboot/$tree/$target/$initmode" + [ -n "$displaymode" ] && \ + elfrom="${elfrom}_$displaymode" + elfrom="$elfrom/coreboot.rom" + + $if_not_dry_build \ + x_ cp "$elfrom" "$tmprom" + + $if_not_dry_build \ + unpad_one_byte "$tmprom" + + [ -n "$payload_uboot" ] && [ "$payload_uboot" != "amd64" ] && \ + [ "$payload_uboot" != "i386" ] && [ "$payload_uboot" != "arm64" ] \ + && err "'$target' defines bad u-boot type '$payload_uboot'" \ + "mkcorebootbin_real" "$@" + + [ -n "$payload_uboot" ] && [ "$payload_uboot" != "arm64" ] && \ + payload_seabios="y" + + [ -z "$uboot_config" ] && \ + uboot_config="default" + [ "$payload_grub" = "y" ] && \ + payload_seabios="y" + [ "$payload_seabios" = "y" ] && [ "$payload_uboot" = "arm64" ] && \ + $if_not_dry_build \ + err "$target: U-Boot arm / SeaBIOS/GRUB both enabled" \ + "mkcorebootbin_real" "$@" + + [ -z "$grub_scan_disk" ] && \ + grub_scan_disk="nvme ahci ata" + [ -z "$grubtree" ] && \ + grubtree="default" + grubelf="elf/grub/$grubtree/$grubtree/payload/grub.elf" + + [ "$payload_memtest" != "y" ] && \ + payload_memtest="n" + [ "$(uname -m)" != "x86_64" ] && \ + payload_memtest="n" + + [ "$payload_grubsea" = "y" ] && [ "$initmode" = "normal" ] && \ + payload_grubsea="n" + [ "$payload_grub" != "y" ] && \ + payload_grubsea="n" + + $if_dry_build \ + return 0 + + [ -f "$cbfscfg" ] && \ + dx_ add_cbfs_option "$cbfscfg" + + if grep "CONFIG_PAYLOAD_NONE=y" "$defconfig"; then + if [ "$payload_seabios" = "y" ]; then + pname="seabios" + add_seabios + fi + if [ "$payload_uboot" = "arm64" ]; then + pname="uboot" + add_uboot + fi + else + pname="custom" + cprom + fi; : +} + +# options for cbfs backend (as opposed to nvram/smmstore): + +add_cbfs_option() +{ + op_name="`printf "%s\n" "$1" | awk '{print $1}'`" + op_arg="`printf "%s\n" "$1" | awk '{print $2}'`" + + if [ -z "$op_name" ] || [ -z "$op_arg" ]; then + return 0 + fi + + ( x_ "$cbfstool" "$tmprom" remove -n "option/$op_name" 1>/dev/null \ + 2>/dev/null ) || : + + x_ "$cbfstool" "$tmprom" add-int -i "$op_arg" -n "option/$op_name" +} + +# in our design, SeaBIOS is also responsible for starting either +# a GRUB or U-Boot payload. this is because SeaBIOS is generally +# a more reliable codebase, so it's less likely to cause a brick +# during testing and development, or user configuration. if one +# of the u-boot or grub payloads fails, the user still has a +# functional SeaBIOS setup to fall back on. watch: + +add_seabios() +{ + [ -n "$payload_uboot" ] && [ "$payload_uboot" != "arm64" ] && \ + $if_not_dry_build \ + add_uboot # add u-boot first, due to fixed cbfs offset + + _seabioself="elf/seabios/default/default/$initmode/bios.bin.elf" + [ "$initmode" = "fspgop" ] && \ + _seabioself="elf/seabios/default/default/libgfxinit/bios.bin.elf" + + _seaname="fallback/payload" + [ "$payload_grubsea" = "y" ] && \ + _seaname="seabios.elf" + + cbfs "$tmprom" "$_seabioself" "$_seaname" + + x_ "$cbfstool" "$tmprom" add-int -i 3000 -n etc/ps2-keyboard-spinup + + opexec="2" + [ "$initmode" = "vgarom" ] && \ + opexec="0" + x_ "$cbfstool" "$tmprom" add-int -i $opexec -n etc/pci-optionrom-exec + + x_ "$cbfstool" "$tmprom" add-int -i 0 -n etc/optionroms-checksum + if [ "$initmode" = "libgfxinit" ] || [ "$initmode" = "fspgop" ]; then + cbfs "$tmprom" "$seavgabiosrom" vgaroms/seavgabios.bin raw + fi + + [ "$payload_memtest" = "y" ] && \ + cbfs "$tmprom" "elf/memtest86plus/memtest.bin" img/memtest + + [ "$payload_grub" = "y" ] && \ + add_grub + + [ "$payload_grubsea" != "y" ] && \ + cprom # seabios, but don't load grub/u-boot first + + # now make seauboot(u-boot loaded by seabios) and SeaGRUB (GRUB loaded + # by SeaBIOS) images; users can bypass via ESC to boot from SeaBIOS + + if [ "$payload_uboot" = "amd64" ] && \ + [ "$displaymode" != "txtmode" ] && \ + [ "$initmode" != "normal" ] && [ "$payload_grubsea" != "y" ]; then + pname="seauboot" + cprom "seauboot" + fi + + if [ "$payload_grub" = "y" ]; then + pname="seagrub" + mkseagrub + fi +} + +add_grub() +{ + # path in CBFS for the GRUB payload + _grubname="img/grub2" + [ "$payload_grubsea" = "y" ] && \ + _grubname="fallback/payload" + + cbfs "$tmprom" "$grubelf" "$_grubname" + + printf "set grub_scan_disk=\"%s\"\n" "$grub_scan_disk" \ + > "$xbtmp/tmpcfg" || \ + err "$target: !insert scandisk" "add_grub" "$@" + + cbfs "$tmprom" "$xbtmp/tmpcfg" scan.cfg raw + + [ "$initmode" != "normal" ] && [ "$displaymode" != "txtmode" ] && \ + cbfs "$tmprom" "$grubdata/background/background1280x800.png" \ + "background.png" raw; : +} + +mkseagrub() +{ + if [ "$payload_grubsea" = "y" ]; then + pname="grub" + else + cbfs "$tmprom" "$grubdata/bootorder" bootorder raw + fi + + fx_ cprom x_ find "$grubdata/keymap" -type f -name "*.gkb" +} + +add_uboot() +{ + if [ "$displaymode" = "txtmode" ]; then + printf "cb/%s: Can't use U-Boot in text mode\n" "$target" 1>&2 + return 0 + elif [ "$initmode" = "normal" ]; then + printf "cb/%s: Can't use U-Boot in normal initmode\n" \ + "$target" 1>&2 + return 0 + fi + + # TODO: re-work to allow each coreboot target to say which ub tree + # instead of hardcoding as in the current logic below: + + # aarch64 targets: + ubcbfsargs="" + ubpath="fallback/payload" + ubtree="default" + ubtarget="$target" + + # override for x86/x86_64 targets: + if [ -n "$payload_uboot" ] && [ "$payload_uboot" != "arm64" ]; then + ubcbfsargs="-l 0x1110000 -e 0x1110000" # 64-bit and 32-bit + # on 64-bit, 0x1120000 is the SPL, with a stub that + # loads it, located at 0x1110000 + + ubpath="img/u-boot" # 64-bit + ubtree="x86_64" + ubtarget="amd64coreboot" + + if [ "$payload_uboot" = "i386" ]; then + ubpath="u-boot" # 32-bit + ubtree="x86" + ubtarget="i386coreboot"; : + fi + fi + + ubdir="elf/u-boot/$ubtree/$ubtarget/$uboot_config" + + ubootelf="$ubdir/u-boot.elf" # aarch64 + [ ! -f "$ubootelf" ] && \ + ubootelf="$ubdir/u-boot" # aarch64 (fallback) + [ "$payload_uboot" = "i386" ] && \ + ubootelf="$ubdir/u-boot-dtb.bin" # x86 override + [ "$payload_uboot" = "amd64" ] && \ + ubootelf="$ubdir/u-boot-x86-with-spl.bin" # x86_64 override + + cbfs "$tmprom" "$ubootelf" "$ubpath" $ubcbfsargs + [ "$payload_seabios" != "y" ] && \ + cprom; : +} + +# prepare the final image in bin/ for user installation: + +cprom() +{ + cpcmd="cp" + + tmpnew="" + newrom="bin/$target/${pname}_${target}_$initmode.rom" + + [ -n "$displaymode" ] && \ + newrom="${newrom%.rom}_$displaymode.rom" + if [ $# -gt 0 ] && [ "${1%.gkb}" != "$1" ]; then + tmpnew="${1##*/}" + newrom="${newrom%.rom}_${tmpnew%.gkb}.rom" + fi + + irom="$tmprom" + + if [ $# -gt 0 ]; then + irom="$(mktemp || err "!mk irom, $(echo "$@")")" || \ + err "can't copy rom" "cprom" "$@" + + x_ cp "$tmprom" "$irom" && cpcmd="mv" + + if [ "${1%.gkb}" != "$1" ]; then + cbfs "$irom" "$grubdata/keymap/$tmpnew" keymap.gkb raw + elif [ "$1" = "seauboot" ]; then + cbfs "$irom" "$grubdata/bootorder_uboot" bootorder raw + fi + fi + + printf "Creating new %s image: '%s'\n" "$projectname" "$newrom" + + x_ mkdir -p "bin/$target" + x_ $cpcmd "$irom" "$newrom" +} + +cbfs() +{ + ccmd="add-payload" + lzma="-c lzma" + + if [ $# -gt 3 ] && [ $# -lt 5 ]; then + ccmd="add" + lzma="-t $4" + elif [ $# -gt 4 ] && [ "$5" = "0x1110000" ]; then + ccmd="add-flat-binary" && \ + lzma="-c lzma -l 0x1110000 -e 0x1110000" + fi + + x_ "$cbfstool" "$1" $ccmd -f "$2" -n "$3" $lzma +} + +# for release files: + +mkcoreboottar() +{ + $if_dry_build \ + return 0 + + if [ "$target" = "$tree" ] || [ "$XBMK_RELEASE" != "y" ] || \ + [ "$release" = "n" ]; then + return 0 + fi + + mkrom_tarball "bin/$target" + x_ ./mk inject "bin/${relname}_${target}.tar.xz" nuke +} diff --git a/include/fw/vendor.sh b/include/fw/vendor.sh new file mode 100644 index 00000000..10daeca3 --- /dev/null +++ b/include/fw/vendor.sh @@ -0,0 +1,624 @@ +# SPDX-License-Identifier: GPL-3.0-only + +# Copyright (c) 2022 Caleb La Grange +# Copyright (c) 2022 Ferass El Hafidi +# Copyright (c) 2023-2026 Leah Rowe + +# These are variables and functions, extending the functionality of +# inject.sh, to be used with lbmk; they are kept separate here, so that +# the main inject.sh can be as similar as possible between lbmk and cbmk, +# so that cherry-picking lbmk patches into cbmk yields fewer merge conflicts. + +# When reading this file, you should imagine that it is part of inject.sh, +# with inject.sh concatenated onto vendor.sh; they are inexorably intertwined. +# The main "mk" script sources vendor.sh first, and then inject.sh, in lbmk. + +e6400_unpack="$xbmkpwd/src/bios_extract/dell_inspiron_1100_unpacker.py" +me7updateparser="$xbmkpwd/util/me7_update_parser/me7_update_parser.py" +pfs_extract="$xbmkpwd/src/biosutilities/Dell_PFS_Extract.py" +uefiextract="$xbmkpwd/elf/uefitool/uefiextract" +bsdtar="$xbmkpwd/elf/libarchive/bsdtar" +bsdunzip="$xbmkpwd/elf/libarchive/bsdunzip" +vendir="vendorfiles" +appdir="$vendir/app" +vfix="DO_NOT_FLASH_YET._FIRST,_INJECT_FILES_VIA_INSTRUCTIONS_ON_LIBREBOOT.ORG_" + +# lbmk-specific extension to the "checkvars" variable (not suitable for cbmk) +checkvarschk="CONFIG_INCLUDE_SMSC_SCH5545_EC_FW CONFIG_HAVE_MRC \ + CONFIG_HAVE_ME_BIN CONFIG_LENOVO_TBFW_BIN CONFIG_VGA_BIOS_FILE \ + CONFIG_FSP_M_FILE CONFIG_FSP_S_FILE CONFIG_KBC1126_FW1 CONFIG_KBC1126_FW2" + +# lbmk-specific extensions to the "checkvars" variable (not suitable for cbmk) +checkvarsxbmk="CONFIG_ME_BIN_PATH CONFIG_SMSC_SCH5545_EC_FW_FILE \ + CONFIG_FSP_FULL_FD CONFIG_KBC1126_FW1_OFFSET CONFIG_KBC1126_FW2_OFFSET \ + CONFIG_FSP_USE_REPO CONFIG_VGA_BIOS_ID CONFIG_BOARD_DELL_E6400 \ + CONFIG_FSP_S_CBFS CONFIG_HAVE_REFCODE_BLOB CONFIG_REFCODE_BLOB_FILE \ + CONFIG_FSP_FD_PATH CONFIG_IFD_BIN_PATH CONFIG_MRC_FILE CONFIG_FSP_M_CBFS" + +# lbmk-specific extensions; general variables +eval "`newvar cbdir cbfstoolref has_hashes hashfile kbc1126_ec_dump mecleaner \ + mfs nuke rom vcfg xromsize _7ztest _dest _dl _dl_bin _me _metmp _pre_dest`" + +# lbmk-specific extensions; declared by pkg.cfg files in config/vendor/ +eval "`newvar DL_hash DL_url DL_url_bkup E6400_VGA_bin_hash E6400_VGA_DL_hash \ + E6400_VGA_DL_url E6400_VGA_DL_url_bkup E6400_VGA_offset E6400_VGA_romname \ + EC_FW1_hash EC_FW2_hash EC_hash EC_url EC_url_bkup FSPFD_hash \ + FSPM_bin_hash FSPS_bin_hash ME11bootguard ME11delta ME11pch ME11sku \ + ME11version ME_bin_hash MEcheck MEclean MEshrink MRC_bin_hash \ + MRC_refcode_cbtree MRC_refcode_gbe REF_bin_hash SCH5545EC_bin_hash \ + SCH5545EC_DL_hash SCH5545EC_DL_url SCH5545EC_DL_url_bkup TBFW_bin_hash \ + TBFW_hash TBFW_size TBFW_url TBFW_url_bkup XBMKmecleaner`" + +download() +{ + [ $# -lt 1 ] && \ + err "No argument given" "download" "$@" + + export PATH="$PATH:/sbin" + board="$1" + + check_target || return 0 + readkconfig download +} + +getfiles() +{ + [ -n "$CONFIG_HAVE_ME_BIN" ] && \ + fetch intel_me "$DL_url" "$DL_url_bkup" "$DL_hash" \ + "$CONFIG_ME_BIN_PATH" curl "$ME_bin_hash" + [ -n "$CONFIG_INCLUDE_SMSC_SCH5545_EC_FW" ] && \ + fetch sch5545ec "$SCH5545EC_DL_url" "$SCH5545EC_DL_url_bkup" \ + "$SCH5545EC_DL_hash" "$CONFIG_SMSC_SCH5545_EC_FW_FILE" \ + "curl" "$SCH5545EC_bin_hash" + [ -n "$CONFIG_KBC1126_FW1" ] && \ + fetch kbc1126ec "$EC_url" "$EC_url_bkup" "$EC_hash" \ + "$CONFIG_KBC1126_FW1" curl "$EC_FW1_hash" + [ -n "$CONFIG_KBC1126_FW2" ] && \ + fetch kbc1126ec "$EC_url" "$EC_url_bkup" "$EC_hash" \ + "$CONFIG_KBC1126_FW2" curl "$EC_FW2_hash" + [ -n "$CONFIG_VGA_BIOS_FILE" ] && \ + fetch e6400vga "$E6400_VGA_DL_url" "$E6400_VGA_DL_url_bkup" \ + "$E6400_VGA_DL_hash" "$CONFIG_VGA_BIOS_FILE" "curl" \ + "$E6400_VGA_bin_hash" + [ -n "$CONFIG_HAVE_MRC" ] && \ + fetch "mrc" "$MRC_url" "$MRC_url_bkup" "$MRC_hash" \ + "$CONFIG_MRC_FILE" "curl" "$MRC_bin_hash" + [ -n "$CONFIG_REFCODE_BLOB_FILE" ] && \ + fetch "refcode" "$MRC_url" "$MRC_url_bkup" "$MRC_hash" \ + "$CONFIG_REFCODE_BLOB_FILE" "curl" "$REF_bin_hash" + [ -n "$CONFIG_LENOVO_TBFW_BIN" ] && \ + fetch "tbfw" "$TBFW_url" "$TBFW_url_bkup" "$TBFW_hash" \ + "$CONFIG_LENOVO_TBFW_BIN" "curl" "$TBFW_bin_hash" + [ -n "$CONFIG_FSP_M_FILE" ] && \ + fetch "fsp" "$CONFIG_FSP_FD_PATH" "$CONFIG_FSP_FD_PATH" \ + "$FSPFD_hash" "$CONFIG_FSP_M_FILE" "copy" "$FSPM_bin_hash" + [ -n "$CONFIG_FSP_S_FILE" ] && \ + fetch "fsp" "$CONFIG_FSP_FD_PATH" "$CONFIG_FSP_FD_PATH" \ + "$FSPFD_hash" "$CONFIG_FSP_S_FILE" copy "$FSPS_bin_hash"; : +} + +fetch() +{ + dl_type="$1" + dl="$2" + dl_bkup="$3" + dlsum="$4" + _dest="${5##*../}" + _pre_dest="$XBMK_CACHE/tmpdl/check" + dlop="$6" + binsum="$7" + + [ -z "$binsum" ] && \ + err "binsum is empty (no checksum)" "fetch" "$@" + + _dl="$XBMK_CACHE/file/$dlsum" # internet file to extract from e.g. .exe + _dl_bin="$XBMK_CACHE/file/$binsum" # extracted file e.g. me.bin + + [ "$5" = "/dev/null" ] && \ + return 0 + + # an extracted vendor file will be placed in pre_dest first, for + # verifying its checksum. if it matches, it is later moved to _dest + remkdir "${_pre_dest%/*}" "$appdir" + + # HACK: if grabbing fsp from coreboot, fix the path for lbmk + if [ "$dl_type" = "fsp" ]; then + dl="${dl##*../}" + _cdp="$dl" + + [ ! -f "$_cdp" ] && \ + _cdp="$cbdir/$_cdp" + [ -f "$_cdp" ] && \ + dl="$_cdp" + + dl_bkup="${dl_bkup##*../}" + _cdp="$dl_bkup" + + [ ! -f "$_cdp" ] && \ + _cdp="$cbdir/$_cdp" + [ -f "$_cdp" ] && \ + dl_bkup="$_cdp"; : + fi + + # download the file (from the internet) to extract from: + + xbget "$dlop" "$dl" "$dl_bkup" "$_dl" "$dlsum" + x_ rm -Rf "${_dl}_extracted" + + # skip extraction if a cached extracted file exists: + + ( xbget copy "$_dl_bin" "$_dl_bin" "$_dest" "$binsum" 2>/dev/null ) || : + [ -f "$_dest" ] && \ + return 0 + + x_ mkdir -p "${_dest%/*}" + + if [ "$dl_type" != "fsp" ]; then + extract_archive "$_dl" "$appdir" || \ + [ "$dl_type" = "e6400vga" ] || \ + err "$_dest $dl_type: !extract" "fetch" "$@" + fi + + x_ extract_$dl_type "$_dl" "$appdir" + set -u -e + + # some functions don't output directly to the given file, _pre_dest. + # instead, they put multiple files there, but we need the one matching + # the given hashsum. So, search for a matching file via bruteforce: + ( fx_ "mkdst $binsum" x_ find "${_pre_dest%/*}" -type f ) || : + + bad_checksum "$binsum" "$_dest" || \ + [ ! -f "$_dest" ] || \ + return 0; : + + [ -z "$binsum" ] && \ + printf "'%s': checksum undefined\n" "$_dest" 1>&2 + + if [ -L "$_dest" ]; then + printf "WARNING: '%s' is a link!\n" "$_dest" 1>&2 + else + x_ rm -f "$_dest" + fi + + err "Can't safely extract '$_dest', for board '$board'" "fetch" "$@" +} + +mkdst() +{ + if bad_checksum "$1" "$2" 2>/dev/null; then + x_ rm -f "$2" + else + x_ mv "$2" "$_dl_bin" + x_ cp "$_dl_bin" "$_dest" + + exit 1 + fi +} + +extract_intel_me() +{ + if e "$mecleaner" f missing; then + err "$cbdir: me_cleaner missing" "extract_intel_me" "$@" + fi + + mfs="" + _7ztest="$xbtmp/metmp/a" + _metmp="$xbtmp/me.bin" + + x_ rm -f "$_metmp" "$xbtmp/a" + x_ rm -Rf "$_7ztest" + + # maintain compatibility with older configs + # because in the past, shrink was assumed + [ -z "$MEshrink" ] && \ + MEshrink="y" + [ "$MEshrink" != "y" ] && [ "$MEshrink" != "n" ] && \ + err "MEshrink set badly on '$board' vendor config" + + if [ "$ME11bootguard" = "y" ]; then + if [ -z "$ME11delta" ] || [ -z "$ME11version" ] || \ + [ -z "$ME11sku" ] || [ -z "$ME11pch" ]; then + err "$board: ME11delta/ME11version/ME11sku/ME11pch" \ + "extract_intel_me" "$@" + fi + + x_ ./mk -f deguard + fi + + set +u +e + + ( fx_ find_me x_ find "$xbmkpwd/$appdir" -type f ) || :; : + + set -u -e + + if [ "$ME11bootguard" != "y" ]; then + x_ mv "$_metmp" "$_pre_dest" + else + ( apply_deguard_hack ) || \ + err "deguard error on '$_dest'" "extract_intel_me" "$@"; : + fi +} + +# bruteforce Intel ME extraction. +# must be called inside a subshell. +find_me() +{ + [ -f "$_metmp" ] && \ + exit 1 # me.bin found + [ -L "$1" ] && \ + return 0 # symlinks disabled for security reasons + + _7ztest="${_7ztest}a" + + _r="-r" # re-locate modules + _trunc="-t" # -t: truncate the ME size + eval "`newvar _keep _pass`" # -k (keep fptr modules), -p (skip checks) + + [ "$ME11bootguard" = "y" ] && \ + mfs="--whitelist MFS" + if [ "$MEclean" = "n" ]; then + MEshrink="n" + _keep="-k" # keep ME modules, don't delete anything + mfs="" # no MFS whitelist needed, due to -r: + fi + if [ "$MEclean" = "n" ] || [ "$MEshrink" != "y" ]; then + eval "`newvar _r _trunc`" + fi + [ "$MEcheck" = "n" ] && \ + _pass="-p" # skip fptr check + [ -n "$mfs" ] && \ + _r="" # cannot re-locate modules if using --whitelist MFS + + if "$mecleaner" $mfs $_r $_keep $_pass $_trunc -O "$xbtmp/a" \ + -M "$_metmp" "$1" || [ -f "$_metmp" ]; then + : # me.bin extracted from a full image with ifd, then shrunk + elif "$mecleaner" $mfs $_r $_pass $_keep $_trunc -O "$_metmp" "$1" || \ + [ -f "$_metmp" ]; then + : # me.bin image already present, and we shrunk it + elif "$me7updateparser" $_keep -O "$_metmp" "$1"; then + : # thinkpad sandybridge me.bin image e.g. x220/t420 + elif extract_archive "$1" "$_7ztest"; then + : # scan newly extracted archive within extracted archive + else + return 0 # can't extract, so try the next file + fi + + [ -f "$_metmp" ] && \ + exit 1 # me.bin found + + ( fx_ find_me x_ find "$_7ztest" -type f ) || exit 1; : # 1==me found +} + +apply_deguard_hack() +{ + x_ cd src/deguard + + x_ ./finalimage.py --delta "data/delta/$ME11delta" \ + --version "$ME11version" --pch "$ME11pch" --sku "$ME11sku" \ + --fake-fpfs data/fpfs/zero --input "$_metmp" --output "$_pre_dest" +} + +extract_archive() +{ + innoextract "$1" -d "$2" || \ + python "$pfs_extract" "$1" -e || \ + 7z x "$1" -o"$2" || \ + "$bsdtar" -C "$2" -xf "$1" || \ + "$bsdunzip" "$1" -d "$2" || \ + return 1 + + [ -d "${_dl}_extracted" ] && \ + x_ cp -R "${_dl}_extracted" "$2"; : +} + +extract_kbc1126ec() +{ + ( extract_kbc1126ec_dump ) || \ + err "$board: can't extract kbc1126 fw" "extract_kbc1126ec" "$@" + + # throw error if either file is missing + x_ e "$appdir/ec.bin.fw1" f + x_ e "$appdir/ec.bin.fw2" f + + x_ cp "$appdir/"ec.bin.fw* "${_pre_dest%/*}/" +} + +extract_kbc1126ec_dump() +{ + x_ cd "$appdir/" + + mv Rompaq/68*.BIN ec.bin || \ + unar -D ROM.CAB Rom.bin || \ + unar -D Rom.CAB Rom.bin || \ + unar -D 68*.CAB Rom.bin || \ + err "!kbc1126 unar" "extract_kbc1126ec" "$@" + + [ ! -f "ec.bin" ] && \ + x_ mv Rom.bin ec.bin + + x_ e ec.bin f + x_ "$kbc1126_ec_dump" ec.bin +} + +extract_e6400vga() +{ + set +u +e + + if [ -z "$E6400_VGA_offset" ] || [ -z "$E6400_VGA_romname" ]; then + err "$board: E6400_VGA_romname/E6400_VGA_offset unset" \ + "extract_e6400vga" "$@" + fi + + tail -c +$E6400_VGA_offset "$_dl" | gunzip > "$appdir/bios.bin" || : + + ( + x_ cd "$appdir" + x_ e "bios.bin" f + "$e6400_unpack" bios.bin || printf "TODO: fix dell extract util\n" + ) || err "can't extract e6400 vga rom" "extract_e6400vga" "$@" + + x_ cp "$appdir/$E6400_VGA_romname" "$_pre_dest" + + set -u -e +} + +extract_sch5545ec() +{ + # full system ROM (UEFI), to extract with UEFIExtract: + _bios="${_dl}_extracted/Firmware/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! + + x_ "$uefiextract" "$_bios" + x_ cp "$_sch5545ec_fw" "$_pre_dest" +} + +# Lenovo ThunderBolt firmware updates: +# https://pcsupport.lenovo.com/us/en/products/laptops-and-netbooks/thinkpad-t-series-laptops/thinkpad-t480-type-20l5-20l6/20l5/solutions/ht508988 +extract_tbfw() +{ + [ -z "$TBFW_size" ] && \ + err "$board: TBFW_size unset" "extract_tbfw" "$@" + + fx_ copytb x_ find "$appdir" -type f -name "TBT.bin" +} + +copytb() +{ + if [ -f "$1" ] && [ ! -L "$1" ]; then + x_ dd if=/dev/null of="$1" bs=1 seek=$TBFW_size + x_ mv "$1" "$_pre_dest" + + return 1 + fi +} + +extract_fsp() +{ + x_ python "$cbdir/3rdparty/fsp/Tools/SplitFspBin.py" split -f "$1" \ + -o "${_pre_dest%/*}" -n "Fsp.fd" +} + +setvfile() +{ + [ -n "$vcfg" ] && for c in $checkvarschk + do + do_getvfile="n" + vcmd="[ \"\${$c}\" != \"/dev/null\" ] && [ -n \"\${$c}\" ]" + + eval "$vcmd && do_getvfile=\"y\"" + + [ "$do_getvfile" = "y" ] && \ + if getvfile "$@"; then + return 0 + fi; : + done && return 1; : +} + +getvfile() +{ + if e "config/vendor/$vcfg/pkg.cfg" f missing; then + return 1 + fi + + . "config/vendor/$vcfg/pkg.cfg" || \ + err "Can't read 'config/vendor/$vcfg/pkg.cfg'" "getvfile" "$@" + + bootstrap + + if [ $# -gt 0 ]; then + # download vendor files + + getfiles + else + # inject vendor files + + fx_ prep x_ find "$tmpromdir" -maxdepth 1 -type f -name "*.rom" + ( check_vendor_hashes ) || \ + err "$archive: Can't verify hashes" "getvfile" "$@"; : + fi + +} + +bootstrap() +{ + cbdir="src/coreboot/$tree" + kbc1126_ec_dump="$xbmkpwd/$cbdir/util/kbc1126/kbc1126_ec_dump" + cbfstool="elf/coreboot/$tree/cbfstool" + rmodtool="elf/coreboot/$tree/rmodtool" + + mecleaner="$xbmkpwd/$cbdir/util/me_cleaner/me_cleaner.py" + [ "$XBMKmecleaner" = "y" ] && \ + mecleaner="$xbmkpwd/src/me_cleaner/me_cleaner.py" + + x_ ./mk -f coreboot "${cbdir##*/}" + x_ ./mk -f me_cleaner + + x_ ./mk -b bios_extract + x_ ./mk -b biosutilities + x_ ./mk -b uefitool + x_ ./mk -b libarchive # for bsdtar and bsdunzip + + [ -d "${kbc1126_ec_dump%/*}" ] && \ + x_ make -C "$cbdir/util/kbc1126" + + if [ -n "$MRC_refcode_cbtree" ]; then + cbfstoolref="elf/coreboot/$MRC_refcode_cbtree/cbfstool" + x_ ./mk -d coreboot "$MRC_refcode_cbtree"; : + fi +} + +prep() +{ + _xrom="$1" + _xromname="${1##*/}" + _xromnew="${_xrom%/*}/${_xromname#"$vfix"}" + + [ "$nuke" = "nuke" ] && \ + _xromnew="${_xrom%/*}/$vfix${_xrom##*/}" + + if e "$_xrom" f missing; then + return 0 + fi + + [ -z "${_xromname#"$vfix"}" ] && \ + err "$_xromname / $vfix: name match" "prep" "$@" + + # Remove the prefix and 1-byte pad + if [ "${_xromname#"$vfix"}" != "$_xromname" ] \ + && [ "$nuke" != "nuke" ]; then + + unpad_one_byte "$_xrom" + x_ mv "$_xrom" "$_xromnew" + + _xrom="$_xromnew" + fi + + if [ "$nuke" = "nuke" ]; then + ( mksha512 "$_xrom" "vendorhashes" ) || err; : + fi + + add_vfiles "$_xrom" || \ + return 1 # no need to insert files + + if [ "$nuke" = "nuke" ]; then + pad_one_byte "$_xrom" + x_ mv "$_xrom" "$_xromnew" + fi +} + +mksha512() +{ + build_sbase + + [ "${1%/*}" != "$1" ] && \ + x_ cd "${1%/*}" + + x_ "$sha512sum" ./"${1##*/}" >> "$2" || \ + err "!sha512sum \"$1\" > \"$2\"" "mksha512" "$@" +} + +add_vfiles() +{ + rom="$1" + + if [ "$has_hashes" != "y" ] && [ "$nuke" != "nuke" ]; then + printf "'%s' has no hash file. Skipping.\n" "$archive" 1>&2 + return 1 + elif [ "$has_hashes" = "y" ] && [ "$nuke" = "nuke" ]; then + printf "'%s' has a hash file. Skipping nuke.\n" "$archive" 1>&2 + return 1 + fi + + [ -n "$CONFIG_HAVE_REFCODE_BLOB" ] && \ + vfile "fallback/refcode" "$CONFIG_REFCODE_BLOB_FILE" "stage" + [ "$CONFIG_HAVE_MRC" = "y" ] && \ + vfile "mrc.bin" "$CONFIG_MRC_FILE" "mrc" "0xfffa0000" + [ "$CONFIG_HAVE_ME_BIN" = "y" ] && \ + vfile IFD "$CONFIG_ME_BIN_PATH" me + [ -n "$CONFIG_KBC1126_FW1" ] && \ + vfile ecfw1.bin "$CONFIG_KBC1126_FW1" raw \ + "$CONFIG_KBC1126_FW1_OFFSET" + [ -n "$CONFIG_KBC1126_FW2" ] && \ + vfile ecfw2.bin "$CONFIG_KBC1126_FW2" raw \ + "$CONFIG_KBC1126_FW2_OFFSET" + [ -n "$CONFIG_VGA_BIOS_FILE" ] && [ -n "$CONFIG_VGA_BIOS_ID" ] && \ + vfile "pci$CONFIG_VGA_BIOS_ID.rom" "$CONFIG_VGA_BIOS_FILE" \ + optionrom + [ "$CONFIG_INCLUDE_SMSC_SCH5545_EC_FW" = "y" ] && \ + [ -n "$CONFIG_SMSC_SCH5545_EC_FW_FILE" ] && \ + vfile sch5545_ecfw.bin "$CONFIG_SMSC_SCH5545_EC_FW_FILE" raw + [ -z "$CONFIG_FSP_USE_REPO" ] && [ -z "$CONFIG_FSP_FULL_FD" ] && \ + [ -n "$CONFIG_FSP_M_FILE" ] && \ + vfile "$CONFIG_FSP_M_CBFS" "$CONFIG_FSP_M_FILE" fsp --xip + [ -z "$CONFIG_FSP_USE_REPO" ] && [ -z "$CONFIG_FSP_FULL_FD" ] && \ + [ -n "$CONFIG_FSP_S_FILE" ] && \ + vfile "$CONFIG_FSP_S_CBFS" "$CONFIG_FSP_S_FILE" fsp + + xchanged="y" + + printf "ROM image successfully patched: %s\n" "$rom" +} + +vfile() +{ + [ "$2" = "/dev/null" ] && \ + return 0 + + cbfsname="$1" + _dest="${2##*../}" + blobtype="$3" + + _offset="" + + if [ "$blobtype" = "fsp" ] && [ $# -gt 3 ]; then + _offset="$4" + elif [ $# -gt 3 ] && _offset="-b $4" && [ -z "$4" ]; then + err "$rom: offset given but empty (undefined)" "vfile" "$@" + fi + + [ "$nuke" != "nuke" ] && \ + x_ e "$_dest" f + + if [ "$cbfsname" = "IFD" ]; then + if [ "$nuke" = "nuke" ]; then + x_ "$ifdtool" $ifdprefix --nuke $blobtype "$rom" \ + -O "$rom" + else + x_ "$ifdtool" $ifdprefix -i $blobtype:$_dest "$rom" \ + -O "$rom" + fi + elif [ "$nuke" = "nuke" ]; then + x_ "$cbfstool" "$rom" remove -n "$cbfsname" + elif [ "$blobtype" = "stage" ]; then + # the only stage we handle is refcode + + x_ rm -f "$xbtmp/refcode" + x_ "$rmodtool" -i "$_dest" -o "$xbtmp/refcode" + x_ "$cbfstool" "$rom" add-stage -f "$xbtmp/refcode" \ + -n "$cbfsname" -t stage + else + x_ "$cbfstool" "$rom" add -f "$_dest" -n "$cbfsname" \ + -t $blobtype $_offset + fi + + xchanged="y" +} + +# must be called from a subshell +check_vendor_hashes() +{ + build_sbase + + x_ cd "$tmpromdir" + + if [ "$has_hashes" != "n" ] && [ "$nuke" != "nuke" ]; then + ( x_ "$sha512sum" -c "$hashfile" ) || \ + x_ sha1sum -c "$hashfile" + fi + + x_ rm -f "$hashfile" +} diff --git a/include/get.sh b/include/get.sh deleted file mode 100644 index 2a9d182b..00000000 --- a/include/get.sh +++ /dev/null @@ -1,292 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-or-later - -# Copyright (c) 2020-2021,2023-2026 Leah Rowe -# Copyright (c) 2022 Caleb La Grange - -eval "`newvar url bkup_url depend loc subcurl subcurl_bkup subgit subgit_bkup \ - subhash`" - -tmpgit="$xbtmp/gitclone" -tmpgitcache="$xbtmp/tmpgit" - -fetch_targets() -{ - [ -d "src/$project/$tree" ] && \ - return 0 - - git_prep "$url" "$bkup_url" "$xbmkpwd/$configdir/$tree/patches" \ - "src/$project/$tree" "submod" -} - -fetch_project() -{ - xgcctree="" - - . "config/git/$project/pkg.cfg" || \ - err "Can't read config 'config/git/$project/pkg.cfg'" \ - "fetch_project" "@" - - if [ -z "$url" ] || [ -z "$bkup_url" ]; then - err "url/bkup_url not both set 'config/git/$project/pkg.cfg'" \ - "fetch_project" "$@" - fi - - [ -n "$xgcctree" ] && \ - x_ ./mk -f coreboot "$xgcctree" - - [ -n "$depend" ] && \ - for d in $depend ; do - x_ ./mk -f $d - done - - clone_project -} - -clone_project() -{ - singletree "$project" || \ - return 0 - - loc="src/$project" - [ -d "$loc" ] && \ - return 0 - - remkdir "${tmpgit%/*}" - git_prep "$url" "$bkup_url" "$xbmkpwd/config/$project/patches" "$loc" -} - -git_prep() -{ - printf "Creating code directory, src/%s/%s\n" "$project" "$tree" - - _patchdir="$3" - _loc="$4" # $1 and $2 are gitrepo and gitrepo_backup - - [ -z "$rev" ] && \ - err "$project/$tree: rev not set" "git_prep" "$@" - - xbget git "$1" "$2" "$tmpgit" "$rev" "$_patchdir" - if singletree "$project" || [ $# -gt 4 ]; then - dx_ fetch_submodule "$mdir/module.list" - fi - - [ "$_loc" != "${_loc%/*}" ] && \ - x_ mkdir -p "${_loc%/*}" - - x_ mv "$tmpgit" "$_loc" -} - -fetch_submodule() -{ - mcfgdir="$mdir/${1##*/}" - eval "`newvar st subcurl subcurl_bkup subgit subgit_bkup subhash`" - - if e "$mcfgdir/module.cfg" f missing; then - return 0 - fi - . "$mcfgdir/module.cfg" || \ - err "Can't read '$mcfgdir/module.cfg'" "fetch_submodules" "$@" - - [ -n "$subgit" ] && [ -n "$subgit_bkup" ] && \ - st="git" - [ -n "$subcurl" ] && [ -n "$subcurl_bkup" ] && \ - st="curl$st" - [ "$st" = "curlgit" ] && \ - err "$mdir: git+curl defined" "fetch_submodule" "$@" - [ -z "$st" ] && \ - return 0 - [ -z "$subhash" ] && \ - err "subhash not set" "fetch_submodule" "$@" - - [ "$st" = "git" ] && \ - x_ rm -Rf "$tmpgit/$1" - - eval "xbget \"\$st\" \"\$sub$st\" \"\$sub${st}_bkup\" \"\$tmpgit/\$1\" \ - \"\$subhash\" \"\$mdir/\${1##*/}/patches\"" -} - -# TODO: in the following functions, argument numbers are used -# which is hard to understand. the code should be modified -# so that variable names are used instead, for easy reading - -xbget() -{ - [ "$1" != "curl" ] && [ "$1" != "copy" ] && [ "$1" != "git" ] && \ - err "Bad dlop (arg 1)" "xbget" "$@" - - for url in "$2" "$3"; do - [ -z "$url" ] && \ - err "empty URL given in" "xbget" "$@" - try_fetch_$1 "$url" "$@" || \ - continue - [ -e "$4" ] && \ - return 0; : # successful download/copy - done - - err "failed to download file/repository" "xbget" "$@"; : -} - -try_fetch_git() -{ - # 1st argument $1 is the current git remote being tried, - # let's say it was https://foo.example.com/repo, then cached - # directories becomes cache/mirror/foo.example.com/repo - - cached="clone" - [ "$XBMK_CACHE_MIRROR" = "y" ] && \ - cached="mirror" - cached="$cached/${1#*://}" - cached="$XBMK_CACHE/$cached" - - x_ mkdir -p "${5%/*}" "${cached%/*}" - - try_$2 "$cached" "$@" || \ - return 1 - [ ! -d "$cached" ] && \ - return 1 - - if [ ! -d "$5" ]; then - tmpclone "$cached" "$5" "$6" "$7" || \ - err "Can't clone final repo" "try_fetch" "$@"; : - fi - - [ ! -d "$5" ] && \ - return 1; : -} - -try_fetch_copy() -{ - try_fetch_curl "$@" || return 1; : -} - -try_fetch_curl() -{ - cached="file/$6" - cached="$XBMK_CACHE/$cached" - - x_ mkdir -p "${5%/*}" "${cached%/*}" - - if bad_checksum "$6" "$cached" 2>/dev/null; then - x_ rm -f "$cached" - fi - - [ -f "$cached" ] || \ - try_$2 "$cached" "$@" || \ - return 1 - - [ -f "$5" ] && \ - if bad_checksum "$6" "$5" 2>/dev/null; then - x_ cp "$cached" "$5" - fi - - if [ ! -f "$cached" ]; then - return 1 - elif bad_checksum "$6" "$cached"; then - x_ rm -f "$cached" - return 1 - fi - - [ "$cached" != "$5" ] && \ - x_ cp "$cached" "$5" - - if bad_checksum "$6" "$5"; then - x_ rm -f "$5" - return 1 - elif [ ! -f "$5" ]; then - return 1 - fi -} - -try_curl() -{ - ua="Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0" - - ( x_ curl --location --retry 3 -A "$ua" "$2" -o "$1" ) \ - || ( x_ wget --tries 3 -U "$ua" "$2" -O "$1" ) \ - || return 1; : -} - -try_copy() -{ - ( x_ cp "$2" "$1" ) || return 1; : -} - -try_git() -{ - gitdest="`findpath "$1" || err "Can't get findpath for '$1'"`" || \ - err "failed findpath for '$1'" try_get "$@" - - x_ rm -Rf "$tmpgitcache" - - if [ ! -d "$gitdest" ]; then - if [ "$XBMK_CACHE_MIRROR" = "y" ]; then - ( x_ git clone --mirror "$2" "$tmpgitcache" ) || \ - return 1 - else - ( x_ git clone "$2" "$tmpgitcache" ) || return 1 - fi - - x_ mkdir -p "${gitdest%/*}" - x_ mv "$tmpgitcache" "$gitdest" - fi - - if git -C "$gitdest" show "$7" 1>/dev/null 2>/dev/null && \ - [ "$forcepull" != "y" ]; then - # don't try to pull the latest changes if the given target - # revision already exists locally. this saves a lot of time - # during release builds, and reduces the chance that we will - # interact with grub.git or gnulib.git overall during runtime - - return 0 - fi - - if [ "$XBMK_CACHE_MIRROR" = "y" ]; then - ( x_ git -C "$gitdest" fetch ) || :; : - ( x_ git -C "$gitdest" update-server-info ) || :; : - else - ( x_ git -C "$gitdest" pull --all ) || :; : - fi -} - -bad_checksum() -{ - if e "$2" f missing; then - return 0 - fi - - build_sbase - csum="$(x_ "$sha512sum" "$2" | awk '{print $1}')" || \ - err "!sha512 '$2' $1" bad_checksum "$@" - - [ "$csum" = "$1" ] && \ - return 1 - - x_ rm -f "$2" - printf "BAD SHA512 %s, '%s'; need %s\n" "$csum" "$2" "$1" 1>&2 -} - -tmpclone() -{ - ( x_ git clone "$1" "$2" ) || return 1 - ( x_ git -C "$2" reset --hard "$3" ) || return 1 - - [ ! -d "$4" ] && \ - return 0 - - tmpclone_patchlist="`mktemp || err "Can't create tmp patch list"`" || \ - err "Can't create tmp patch list" "tmpclone" "$@" - - x_ find "$4" -type f | sort > "$tmpclone_patchlist" || \ - err "Can't write patch names to '$tmpclone_patchlist'" \ - "tmpclone" "$@" - - while read -r tmpclone_patch; do - - ( x_ git -C "$2" am -3 --keep-cr "$tmpclone_patch" ) || \ - err "Can't apply '$tmpclone_patch'" "tmpclone" "$@"; : - - done < "$tmpclone_patchlist" || \ - err "Can't read '$tmpclone_patchlist'" "tmpclone" "$@" - - x_ rm -f "$tmpclone_patchlist" -} diff --git a/include/init.sh b/include/init.sh deleted file mode 100644 index 9adeee60..00000000 --- a/include/init.sh +++ /dev/null @@ -1,398 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only - -# Copyright (c) 2022 Caleb La Grange -# Copyright (c) 2022 Ferass El Hafidi -# Copyright (c) 2020-2026 Leah Rowe -# Copyright (c) 2025 Alper Nebi Yasak - -projectname="libreboot" -projectsite="https://libreboot.org/" - -sha512sum="util/sbase/sha512sum" - -eval "`newvar aur_notice basetmp board checkvarschk checkvarsxbmk configdir \ - datadir is_child python pyver reinstall relname version versiondate \ - xbmklock xbmkpath xbmkpwd xbmkpwd xbtmp`" - -xbmk_init() -{ - xbmkpwd="`pwd || err "Cannot generate PWD"`" || err "!" xbmk_init "$@" - xbmklock="$xbmkpwd/lock" - basetmp="$xbmkpwd/xbmkwd" - sha512sum="$xbmkpwd/util/sbase/sha512sum" - - if [ $# -gt 0 ] && [ "$1" = "dependencies" ]; then - x_ xbmkpkg "$@" - exit 0 - fi - - id -u 1>/dev/null 2>/dev/null || \ - err "suid check failed" "xbmk_init" "$@" - - [ "$(id -u)" = "0" ] && \ - err "this command as root is not permitted" "xbmk_init" "$@" - - export PWD="$xbmkpwd" - x_ mkdir -p "$basetmp" "cache" - - for init_cmd in get_version set_env set_threads git_init child_exec; do - xbmk_$init_cmd "$@" || \ - break; : - done -} - -xbmkpkg() -{ - xchk xbmkpkg "$@" - - [ $# -gt 2 ] && \ - reinstall="$3" - - . "config/dependencies/$2" || \ - err "Can't read 'config/dependencies/$2'" "xbmkpkg" "$@" - - if [ -z "$pkg_add" ] || [ -z "$pkglist" ]; then - err "pkg_add/pkglist not both set" "xbmkpkg" "$@" - fi - - if [ "$2" == "gentoo" ]; then - - if [ -z "$pkg_use" ] || [ -z "$pkg_use_file" ]; then - err "pkg_use/pkg_use_file not both set" "xbmkpkg" "$@" - fi - - printf "Updating package use...\n" - printf "Writing into %s" "$pkg_use_file..." - - x_ mkdir -p "`dirname $pkg_use_file`" - - printf "%s\n" "$pkg_use" >> "$pkg_use_file" - fi - - x_ $pkg_add $pkglist - - [ -n "$aur_notice" ] && \ - printf "You need AUR packages: %s\n" "$aur_notice" 1>&2; : -} - -xbmk_get_version() -{ - [ ! -f ".version" ] || \ - read -r version < ".version" || \ - err "can't read version file" "xbmk_get_version" "$@" - [ ! -f ".versiondate" ] || \ - read -r versiondate < ".versiondate" || \ - err "can't read versiondate" xbmk_get_version "$@" - - [ -f ".version" ] && [ -z "$version" ] && \ - err "version not set" "xbmk_get_version" "$@" - [ -f ".versiondate" ] && [ -z "$versiondate" ] && \ - err "versiondate not set" "xbmk_get_version" "$@" - - [ ! -e ".git" ] && [ ! -f ".version" ] && \ - version="unknown" - [ ! -e ".git" ] && [ ! -f ".versiondate" ] && \ - versiondate="1716415872" - - xbmk_sanitize_version - - [ -n "$version" ] && \ - relname="$projectname-$version"; : -} - -# a parent instance will cause this function to return 0. -# a child instance will return 1, skipping further initialisation -# after this function is called. -xbmk_set_env() -{ - is_child="n" - xbmkpath="$PATH" - - # unify all temporary files/directories in a single TMPDIR - [ -n "${TMPDIR+x}" ] && [ "${TMPDIR%_*}" != "$basetmp/xbmk" ] && \ - unset TMPDIR - if [ -n "${TMPDIR+x}" ]; then - export TMPDIR="$TMPDIR" - xbtmp="$TMPDIR" - fi - [ -n "${TMPDIR+x}" ] && \ - is_child="y" - - if [ "$is_child" = "y" ]; then - xbmk_child_set_env - return 1 # child instance. discontinue initialisation. - fi - xbmk_parent_set_env -} - -xbmk_child_set_env() -{ - xbmk_child_set_tmp - - [ -z "${XBMK_CACHE+x}" ] && \ - err "XBMK_CACHE unset on child" "xbmk_set_env" "$@" - [ -z "${XBMK_THREADS+x}" ] && \ - xbmk_set_threads - [ -z "${XBMK_CACHE_MIRROR+x}" ] && \ - xbmk_set_mirror; : -} - -xbmk_child_set_tmp() -{ - eval "`newvar badtmp locktmp xbtmpchk`" - - xbtmpchk="`findpath "$TMPDIR" || err "!findpath $TMPDIR"`" || \ - err "!findpath '$TMPDIR'" "xbmk_child_set_tmp" "$@" - - read -r locktmp < "$xbmklock" || \ - err "can't read '$xbmklock'" "xbmk_child_set_tmp" "$@" - - if [ "$locktmp" != "$xbtmpchk" ]; then - badtmp="TMPDIR '$xbtmpchk' changed; was '$locktmp'" - printf "bad TMPDIR init, '%s': %s\n" "$TMPDIR" "$badtmp" 1>&2 - err "'$xbmklock' present with bad tmpdir. is a build running?" - fi - - xbtmp="$xbtmpchk" - export TMPDIR="$xbtmpchk" -} - -xbmk_parent_set_env() -{ - xbmk_parent_check_tmp - - printf "%s\n" "$xbtmp" > "$xbmklock" || \ - err "cannot create '$xbmklock'" xbmk_set_env "$@"; : - - # not really critical for security, but it's a barrier - # against the user to make them think twice before deleting it - # in case an actual instance of xbmk is already running: - - x_ chmod -w "$xbmklock" - - xbmk_parent_set_export - xbmk_set_version - - remkdir "$xbtmp" "$xbtmp/gnupath" "$xbtmp/xbmkpath" - - xbmk_set_pyver - xbmk_set_mirror -} - -xbmk_parent_check_tmp() -{ - export TMPDIR="$basetmp" - - xbmklist="`mktemp || err "can't make tmplist"`" || \ - err "can't make tmplist" xbmk_parent_check_tmp "$@" - - x_ rm -f "$xbmklist" - x_ touch "$xbmklist" - - for xtmpdir in "$basetmp"/xbmk_*; do - if [ -e "$xtmpdir" ]; then - printf "%s\n" "$xtmpdir" >> "$xbmklist" || \ - err "can't write '$xtmpdir' to '$xbmklist'" \ - "xbmk_parent_check_tmp" "$@"; : - fi - done - - # set up a unified temporary directory, for common deletion later: - export TMPDIR="`x_ mktemp -d -t xbmk_XXXXXXXX`" || \ - err "can't export TMPDIR" "xbmk_parent_check_tmp" "$@" - xbtmp="$TMPDIR" - - while read -r xtmpdir; do - [ "$xtmpdir" = "$xbtmp" ] && \ - err "pre-existing $xbtmp" xbmk_parent_check_tmp "$@"; : - done < "$xbmklist" || \ - err "Can't read xbmklist: '$xbmklist'" "xbmk_parent_check_tmp" "$@" - - x_ rm -f "$xbmklist" -} - -xbmk_parent_set_export() -{ - export XBMK_CACHE="$xbmkpwd/cache" - - [ -e "$XBMK_CACHE" ] && [ ! -d "$XBMK_CACHE" ] && \ - err "cachedir '$XBMK_CACHE' is a file" \ - "xbmk_parent_set_export" "$@" - - export PATH="$xbtmp/xbmkpath:$xbtmp/gnupath:$PATH" - xbmkpath="$PATH" - - # if "y": a coreboot target won't be built if target.cfg says release=n - # (this is used to exclude certain build targets from releases) - - [ -z "${XBMK_RELEASE+x}" ] && \ - export XBMK_RELEASE="n" - [ "$XBMK_RELEASE" = "Y" ] && \ - export XBMK_RELEASE="y" - [ "$XBMK_RELEASE" != "y" ] && \ - export XBMK_RELEASE="n"; : -} - -xbmk_set_threads() -{ - [ -z "${XBMK_THREADS+x}" ] && \ - export XBMK_THREADS=1 - expr "X$XBMK_THREADS" : "X-\{0,1\}[0123456789][0123456789]*$" \ - 1>/dev/null 2>/dev/null || \ - export XBMK_THREADS=1; : -} - -xbmk_set_version() -{ - version_="$version" - [ ! -e ".git" ] || \ - version="$(git describe --tags HEAD 2>&1)" || \ - version="git-$(git rev-parse HEAD 2>&1)" || \ - version="$version_" - - versiondate_="$versiondate" - [ ! -e ".git" ] || \ - versiondate="$(git show --no-patch --no-notes \ - --pretty='%ct' HEAD)" || versiondate="$versiondate_" - - update_xbmkver "." - - relname="$projectname-$version" - export LOCALVERSION="-$projectname-${version%%-*}" -} - -xbmk_set_pyver() -{ - python="python3" - pyver="2" - pyv="import sys; print(sys.version_info[:])" - - pybin python3 1>/dev/null || \ - python="python" - [ "$python" = "python3" ] && \ - pyver="3" - pybin "$python" 1>/dev/null || \ - pyver="" - - [ -z "$pyver" ] || \ - "`x_ pybin "$python"`" -c "$pyv" 1>/dev/null \ - 2>/dev/null || \ - err "Can't detect Python version." "xbmk_set_pyver" "$@" - if [ -n "$pyver" ]; then - pyver="$("$(pybin "$python")" -c "$pyv" | awk '{print $1}')" - pyver="${pyver#(}" - pyver="${pyver%,}" - fi - [ "${pyver%%.*}" != "3" ] && \ - err "Bad python version (must by 3.x)" "xbmk_set_pyver" "$@" - - # set up python in PATH (environmental variable): - ( - x_ cd "$xbtmp/xbmkpath" - x_ ln -s "`x_ pybin "$python"`" python || \ - err "can't make symlink" "xbmk_set_pyver" "$@" - - ) || err "Can't link Python in $xbtmp/xbmkpath" xbmk_set_pyver "$@"; : -} - -# Use direct path, to prevent a hang if Python is using a virtual environment, -# not command -v, to prevent a hang when checking python's version -# See: https://docs.python.org/3/library/venv.html#how-venvs-work -pybin() -{ - py="import sys; quit(1) if sys.prefix == sys.base_prefix else quit(0)" - - venv=1 - command -v "$1" 1>/dev/null 2>/dev/null || \ - venv=0 - - [ $venv -lt 1 ] || \ - "$1" -c "$py" 1>/dev/null 2>/dev/null || \ - venv=0 - - # try the direct path from PATH first. the binary specified by venv - # can be called directly, which then removes use of the venv - if [ $venv -gt 0 ] && [ -L "`command -v "$1" 2>/dev/null`" ]; then - pypath="$(findpath \ - "$(command -v "$1" 2>/dev/null)" 2>/dev/null || :)" - if [ -e "$pypath" ] && [ ! -d "$pypath" ] && \ - [ -x "$pypath" ]; then - printf "%s\n" "$pypath" - return 0 - fi - fi - - # if python venv: fall back to common PATH directories for checking: - [ $venv -gt 0 ] && for pypath in "/usr/local/bin" "/usr/bin"; do - if [ -e "$pypath/$1" ] && [ ! -d "$pypath/$1" ] && \ - [ -x "$pypath/$1" ]; then - printf "%s/%s\n" "$pypath" "$1" - return 0 - fi - done && return 1 - - # Defer to normal command -v if not a venv - command -v "$1" 2>/dev/null || \ - return 1; : -} - -xbmk_set_mirror() -{ - # defines whether cache/clone/ (regular clones) - # or cache/mirror (--mirror clones) are used, per project - - # to use cache/mirror/ do: export XBMK_CACHE_MIRROR="y" - # mirror/ stores a separate directory per repository, even per backup. - # it's slower, and uses more disk space, and some upstreams might not - # appreciate it, so it should only be used for development or archival - - [ -z "${XBMK_CACHE_MIRROR+x}" ] && \ - export XBMK_CACHE_MIRROR="n" - [ "$XBMK_CACHE_MIRROR" != "y" ] && \ - export XBMK_CACHE_MIRROR="n"; : -} - -xbmk_git_init() -{ - # the git identity check is only needed for: ./mk -b coreboot [args] - [ "${2-}" = "-b" ] && [ "${3-}" = "coreboot" ] && \ - for gitarg in "user.name" "user.email"; do - git config --includes $gitarg 1>/dev/null 2>/dev/null || \ - err "Run this first: $gitcmd \"your ${gitcmd##*.}\"" \ - "xbmk_git_init" "$@"; : - done - - [ -L ".git" ] && \ - err "'$xbmkpwd/.git' is a symlink" "xbmk_git_init" "$@" - [ -e ".git" ] && \ - return 0 - - ( - export GIT_COMMITTER_DATE="@$versiondate +0000" - export GIT_AUTHOR_DATE="@$versiondate +0000" - - x_ git init 1>/dev/null 2>/dev/null - x_ git add -A . 1>/dev/null 2>/dev/null - x_ git -c user.name="xbmk" -c user.email="xbmk@example.com" \ - commit -m "$projectname $version" \ - --author="xbmk " 1>/dev/null 2>/dev/null - x_ git -c user.name="xbmk" -c user.email="xbmk@example.com" \ - tag -a "$version" -m "$projectname $version" \ - 1>/dev/null 2>/dev/null; : - - ) || err "Can't initialise workdir" xbmk_git_init "$@"; : -} - -xbmk_child_exec() -{ - xbmk_rval=0 - - ( x_ ./mk "$@" ) || xbmk_rval=1 - - ( x_ rm -Rf "$xbtmp" ) || xbmk_rval=1 - ( x_ rm -f "$xbmklock" ) || xbmk_rval=1 - - exit $xbmk_rval -} - -xbmk_init "$@" diff --git a/include/inject.sh b/include/inject.sh deleted file mode 100644 index 0760c1d8..00000000 --- a/include/inject.sh +++ /dev/null @@ -1,205 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only - -# Copyright (c) 2022 Caleb La Grange -# Copyright (c) 2022 Ferass El Hafidi -# Copyright (c) 2023-2026 Leah Rowe - -cbcfgsdir="config/coreboot" -tmpromdel="$XBMK_CACHE/DO_NOT_FLASH" -nvmutil="util/nvmutil/nvmutil" -ifdtool="elf/coreboot/default/ifdtool" - -checkvars="CONFIG_GBE_BIN_PATH ${checkvarsxbmk-} ${checkvarschk-}" - -eval "`newvar archive board boarddir IFD_platform ifdprefix \ - new_mac tmpromdir tree xchanged $checkvars`" - -inject() -{ - remkdir "$tmpromdel" - - [ $# -lt 1 ] && \ - err "No options specified" "inject" "$@" - - archive="$1"; - new_mac="xx:xx:xx:xx:xx:xx" - - nuke="" - xchanged="" - - [ $# -gt 1 ] && case "$2" in - nuke) - new_mac="" - nuke="nuke" - ;; - setmac) - if [ $# -gt 2 ]; then - new_mac="$3" && \ - [ -z "$new_mac" ] && \ - err "Empty MAC address" "inject" "$@"; : - fi - ;; - *) - err "Unrecognised inject mode: '$2'" "inject" "$@" ;; - esac - - [ "$new_mac" = "keep" ] && \ - new_mac="" - - check_release - if check_target; then - patch_release || \ - return 0; : - fi - [ "$xchanged" = "y" ] && \ - remktar - - if [ "$xchanged" = "y" ]; then - printf "\n'%s' was modified\n" "$archive" 1>&2 - else - printf "\n'%s' was NOT modified\n" "$archive" 1>&2 - fi - - x_ rm -Rf "$tmpromdel" -} - -check_release() -{ - [ -L "$archive" ] && \ - err "'$archive' is a symlink" "check_release" "$@" - if e "$archive" f missing; then - err "'$archive' missing" "check_release" "$@" - fi - - archivename="`basename "$archive" || err "Can't get '$archive' name"`" \ - || err "can't get '$archive' name" "check_release" "$@" - - [ -z "$archivename" ] && \ - err "Can't determine archive name" "check_release" "$@" - - case "$archivename" in - *_src.tar.xz) - err "'$archive' is a src archive!" "check_release" "$@" - ;; - grub_*|seagrub_*|custom_*|seauboot_*|seabios_withgrub_*) - err "'$archive' is a ROM image" "check_release" "$@" - ;; - *.tar.xz) _stripped_prefix="${archivename#*_}" - board="${_stripped_prefix%.tar.xz}" - ;; - *) - err "'$archive': cannot detect board" "check_release" "$@" - ;; - esac; : -} - -check_target() -{ - [ "$board" != "${board#serprog_}" ] && \ - return 1 - - boarddir="$cbcfgsdir/$board" - - . "$boarddir/target.cfg" || \ - err "Can't read '$boarddir/target.cfg'" "check_target" "$@" - - [ -z "$tree" ] && \ - err "tree unset in '$boarddir/target.cfg'" "check_target" "$@" - - x_ ./mk -d coreboot "$tree" - - ifdtool="elf/coreboot/$tree/ifdtool" - - [ -n "$IFD_platform" ] && \ - ifdprefix="-p $IFD_platform"; : -} - -patch_release() -{ - [ "$nuke" != "nuke" ] && \ - x_ ./mk download "$board" - - has_hashes="n" - tmpromdir="$tmpromdel/bin/$board" - - remkdir "${tmpromdir%"/bin/$board"}" - x_ tar -xf "$archive" -C "${tmpromdir%"/bin/$board"}" - - for _hashes in "vendorhashes" "blobhashes"; do - if e "$tmpromdir/$_hashes" f; then - has_hashes="y" - hashfile="$_hashes" - - break - fi - done - - readkconfig || \ - return 1 - - [ -n "$new_mac" ] && [ -n "$CONFIG_GBE_BIN_PATH" ] && \ - modify_mac; : -} - -readkconfig() -{ - x_ rm -f "$xbtmp/cbcfg" - fx_ scankconfig x_ find "$boarddir/config" -type f - - if e "$xbtmp/cbcfg" f missing; then - return 1 - fi - - . "$xbtmp/cbcfg" || \ - err "Can't read '$xbtmp/cbcfg'" "readkconfig" "$@" - - setvfile "$@" || \ - return 1; : -} - -scankconfig() -{ - for cbc in $checkvars; do - grep "$cbc" "$1" 2>/dev/null 1>>"$xbtmp/cbcfg" || : - done -} - -modify_mac() -{ - x_ cp "${CONFIG_GBE_BIN_PATH##*../}" "$xbtmp/gbe" - - if [ -n "$new_mac" ] && [ "$new_mac" != "restore" ]; then - x_ make -C util/nvmutil clean - x_ make -C util/nvmutil - - x_ "$nvmutil" "$xbtmp/gbe" setmac "$new_mac" - fi - - fx_ newmac x_ find "$tmpromdir" -maxdepth 1 -type f -name "*.rom" - - printf "\nThe following GbE NVM data will be written:\n" - x_ "$nvmutil" "$xbtmp/gbe" dump | grep -v "bytes read from file" || : -} - -newmac() -{ - if e "$1" f; then - xchanged="y" - x_ "$ifdtool" $ifdprefix -i GbE:"$xbtmp/gbe" "$1" -O "$1" - fi -} - -remktar() -{ - ( - x_ cd "${tmpromdir%"/bin/$board"}" - - printf "Re-building tar archive (please wait)\n" - mkrom_tarball "bin/$board" 1>/dev/null - - ) || err "Cannot re-generate '$archive'" "remktar" "$@" - - mv "${tmpromdir%"/bin/$board"}/bin/${relname}_${board}.tar.xz" \ - "$archive" || \ - err "'$archive' -> Can't overwrite" "remktar" "$@"; : -} diff --git a/include/mk/release.sh b/include/mk/release.sh new file mode 100644 index 00000000..f0dc4864 --- /dev/null +++ b/include/mk/release.sh @@ -0,0 +1,115 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +# Copyright (c) 2023-2026 Leah Rowe + +eval "`newvar reldest reldir relmode rsrc vdir`" + +release() +{ + export XBMK_RELEASE="y" + reldir="release" + + while getopts m: option + do + [ -z "$OPTARG" ] && \ + err "empty argument not allowed" "release" "$@" + [ "$option" != "m" ] && \ + err "invalid option '-$option'" "release" "$@" + + relmode="$OPTARG" + done + + reldest="$reldir/$version" + [ -e "$reldest" ] && \ + err "already exists: \"$reldest\"" "release" "$@" + + vdir="`mktemp -d || err "can't make vdir"`" || \ + err "can't make tmp vdir" "release" "$@" + vdir="$vdir/$version" + rsrc="$vdir/${relname}_src" + + remkdir "$vdir" + x_ git clone . "$rsrc" + update_xbmkver "$rsrc" + + prep_release src + prep_release tarball + [ "$relmode" != "src" ] && \ + prep_release bin + + x_ rm -Rf "$rsrc" + + x_ mkdir -p "$reldir" + x_ mv "$vdir" "$reldir" + x_ rm -Rf "${vdir%"/$version"}" + + printf "\n\nDONE! Check release files under %s\n" "$reldest" +} + +prep_release() +{ + ( + if [ "$1" != "tarball" ]; then + x_ cd "$rsrc" + [ ! -e "cache" ] && \ + x_ ln -s "$XBMK_CACHE" "cache"; : + fi + + prep_release_$1 + + ) || err "can't prep release $1" "prep_release" "$@" +} + +prep_release_src() +{ + x_ cp -R "util/sbase" "util/sbase2" + + x_ ./mk -f + + fx_ "x_ rm -Rf" x_ find . -name ".git" + fx_ "x_ rm -Rf" x_ find . -name ".gitmodules" + + ( fx_ nuke x_ find config -type f -name "nuke.list" ) || \ + err "can't prune project files" "prep_release_src" "$@"; : +} + +nuke() +{ + r="$rsrc/src/${1#config/}" + + if [ -d "${r%/*}" ]; then + x_ cd "${r%/*}" + dx_ "x_ rm -Rf" "$rsrc/$1" + fi +} + +prep_release_tarball() +{ + git log --graph --pretty=format:'%Cred%h%Creset %s %Creset' \ + --abbrev-commit > "$rsrc/CHANGELOG" || \ + err "can't create '$rsrc/CHANGELOG'" "prep_release_tarball" "$@" + + x_ rm -f "$rsrc/lock" "$rsrc/cache" + x_ rm -Rf "$rsrc/xbmkwd" "$rsrc/util/sbase" + x_ mv "$rsrc/util/sbase2" "$rsrc/util/sbase" + + ( + x_ cd "${rsrc%/*}" + x_ mktarball "${rsrc##*/}" "${rsrc##*/}.tar.xz" + + ) || err "can't create src tarball" "prep_release_tarball" "$@"; : +} + +prep_release_bin() +{ + x_ ./mk -d coreboot + + x_ ./mk -b coreboot + x_ ./mk -b pico-serprog + x_ ./mk -b stm32-vserprog + x_ ./mk -b pcsx-redux + + fx_ mkrom_tarball x_ find bin -maxdepth 1 -type d -name "serprog_*" + + x_ mv bin ../roms +} diff --git a/include/mk/tree.sh b/include/mk/tree.sh new file mode 100644 index 00000000..434796e2 --- /dev/null +++ b/include/mk/tree.sh @@ -0,0 +1,628 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +# Copyright (c) 2022-2023 Alper Nebi Yasak +# Copyright (c) 2022 Ferass El Hafidi +# Copyright (c) 2023-2025 Leah Rowe + +# flag e.g. ./mk -b <-- mkflag would be "b" +flag="" + +# macros, overridden depending on the flag +if_do_make="" +if_dry_build=":" +if_not_do_make=":" +if_not_dry_build="" + +eval "`newvar autoconfargs autogenargs badhash badtghash bootstrapargs \ + build_depend buildtype cleanargs cmakedir cmd defconfig dest_dir elfdir \ + forcepull gccdir gccfull gccver gnatdir gnatfull gnatver listfile \ + makeargs mdir mkhelper mkhelpercfg mode postmake premake project release \ + rev srcdir target target_dir targets tree xarch xgcctree xlang`" + +trees() +{ + flags="f:F:b:m:u:c:x:s:l:n:d:" + + while getopts $flags option + do + [ -n "$flag" ] && \ + err "only one flag is permitted" "trees" "$@" + + flag="$1" + + # the "mode" variable is affixed to a make command, example: + # ./mk -m coreboot does: make menuconfig -C src/coreboot/tree + + case "$flag" in + -d) + # -d is similar to -b, except that + # a large number of operations will be + # skipped. these are "if_not_dry_build build" scenarios + # where only a subset of build tasks are done, + # and $if_not_dry_build is prefixed to skipped commands + + if_dry_build="" + if_not_dry_build=":" + ;; + -b) : ;; + -u) mode="oldconfig" ;; + -m) mode="menuconfig" ;; + -c) mode="distclean" ;; + -x) mode="crossgcc-clean" ;; + -f|-F) # download source code for a project + # macros. colon means false. + if_do_make=":" + if_dry_build="" + if_not_do_make="" + if_not_dry_build=":" + [ "$flag" = "-F" ] && \ + forcepull="y"; : # never skip git fetch/pull + ;; + -s) mode="savedefconfig" ;; + -l) mode="olddefconfig" ;; + -n) mode="nconfig" ;; + *) err "invalid option '-$option'" "trees" "$@" ;; + esac + + if [ -z "${OPTARG+x}" ]; then + shift 1 + break + fi + + project="${OPTARG#src/}" + project="${project#config/git/}" + + shift 2 + done + + if [ -z "$flag" ]; then + err "missing flag ($flags)" "trees" "$@" + elif [ -z "$project" ]; then + fx_ "x_ ./mk $flag" x_ ls -1 config/git + return 1 + elif [ ! -f "config/git/$project/pkg.cfg" ]; then + err "config/git/$project/pkg.cfg missing" "trees" "$@" + fi + + elfdir="elf/$project" + datadir="config/data/$project" + configdir="config/$project" + srcdir="src/$project" + dest_dir="$elfdir" + + listfile="$datadir/build.list" + [ ! -f "$listfile" ] && \ + listfile="" # build.list is optional on all projects + + mkhelpercfg="$datadir/mkhelper.cfg" + if e "$mkhelpercfg" f missing; then + mkhelpercfg="$xbtmp/mkhelper.cfg" + x_ touch "$mkhelpercfg" + fi + + targets="$*" + cmd="build_targets $targets" + if singletree "$project"; then + cmd="build_project" + fi + + remkdir "${tmpgit%/*}" +} + +build_project() +{ + configure_project "$configdir" || \ + return 0 + + [ ! -f "$listfile" ] || \ + $if_not_dry_build elfcheck || \ + return 0 + + [ "$mode" = "distclean" ] && \ + mode="clean" + + run_make_command || \ + return 0 + + [ -z "$mode" ] && \ + $if_not_dry_build \ + copy_elf; : +} + +build_targets() +{ + if [ ! -d "$configdir" ]; then + err "directory '$configdir' doesn't exist" "build_targets" "$@" + elif [ $# -lt 1 ]; then + targets="$(ls -1 "$configdir")" || \ + err "'$configdir': can't list targets" "build_targets" "$@" + fi + + for x in $targets + do + unset CROSS_COMPILE + export PATH="$xbmkpath" + + if [ "$x" = "list" ]; then + x_ ls -1 "config/$project" + listfile="" + break + fi + + printf "'make %s', '%s', '%s'\n" "$mode" "$project" "$x" + + target="$x" + + x_ handle_defconfig + + [ -z "$mode" ] && \ + x_ $postmake; : + done; : +} + +handle_defconfig() +{ + target_dir="$configdir/$target" + + [ ! -f "CHANGELOG" ] && \ + fetch_project "$project" + + configure_project "$target_dir" || \ + return 0 + + [ -z "$tree" ] && \ + err "$configdir: 'tree' not set" "handle_defconfig" "$@" + + srcdir="src/$project/$tree" + + [ "$mode" = "${mode%clean}" ] && [ ! -d "$srcdir" ] && \ + return 0 + + for y in "$target_dir/config"/* + do + [ "$flag" != "-d" ] && [ ! -f "$y" ] && \ + continue + [ "$flag" != "-d" ] && \ + defconfig="$y" + + if [ -z "$mode" ]; then + check_defconfig || continue; : + fi + + [ -z "$mode" ] && \ + for _xarch in $xarch; do + $if_dry_build \ + break + [ -n "$_xarch" ] && \ + check_cross_compiler "$_xarch"; : + done; : + + handle_makefile + + [ -z "$mode" ] && \ + $if_not_dry_build \ + copy_elf; : + done; : +} + +configure_project() +{ + _tcfg="$1/target.cfg" + + eval "`newvar autoconfargs badhash badtghash bootstrapargs \ + build_depend buildtype cleanargs makeargs mkhelper postmake \ + premake release xarch xgcctree xlang`" + + [ ! -f "$_tcfg" ] && \ + buildtype="auto" + + # globally initialise all variables for a source tree / target: + if e "$datadir/mkhelper.cfg" f; then + . "$datadir/mkhelper.cfg" || \ + err "Can't read '$datadir/mkhelper.cfg'" \ + "configure_project" "$@" + fi + + # override target/tree specific variables from per-target config: + while e "$_tcfg" f || [ "$cmd" != "build_project" ] + do + printf "Loading %s config: %s\n" "$project" "$_tcfg" + eval "`newvar rev tree`" + + . "$_tcfg" || \ + err "Can't read '$_tcfg'" "configure_project" "$@" + + [ "$flag" = "-d" ] && \ + build_depend="" # dry run + + [ "$cmd" = "build_project" ] && \ + break # single-tree, so targeting is unnecessary + $if_do_make \ + break + [ "${_tcfg%/*/target.cfg}" = "${_tcfg%"/$tree/target.cfg"}" ] \ + && break # target and tree matching was successful + + _tcfg="${_tcfg%/*/target.cfg}/$tree/target.cfg" # try next + done + + [ "$XBMK_RELEASE" = "y" ] && [ "$release" = "n" ] && \ + return 1 + [ -n "$buildtype" ] && [ "${mode%config}" != "$mode" ] && \ + return 1 + + [ -z "$mode" ] && \ + $if_not_dry_build \ + build_dependencies + + mdir="$xbmkpwd/config/submodule/$project" + [ -n "$tree" ] && \ + mdir="$mdir/$tree" + + if [ ! -f "CHANGELOG" ]; then + delete_old_project_files + $if_not_do_make \ + fetch_${cmd#build_} + fi + $if_not_do_make \ + return 1 + + x_ ./mk -f "$project" "$target" +} + +# projects can specify which other projects +# to build first, as declared dependencies: + +build_dependencies() +{ + for bd in $build_depend + do + bd_project="${bd%%/*}" + bd_tree="${bd##*/}" + + [ -z "$bd_project" ] && \ + $if_not_dry_build \ + err "$project/$tree: !bd '$bd'" \ + "build_dependencies" "$@" + [ "${bd##*/}" = "$bd" ] && \ + bd_tree="" + [ -n "$bd_project" ] && \ + $if_not_dry_build \ + x_ ./mk -b $bd_project $bd_tree; : + done; : +} + +# delete_old_project_files along with project_up_to_date, +# concatenates the sha512sum hashes of all files related to +# a project, tree or target, then gets the sha512sum of that +# concatenation. this is checked against any existing +# calculation previously cached; if the result differs, or +# nothing was previously stored, we know to delete resources +# such as builds, project sources and so on, for auto-rebuild: + +delete_old_project_files() +{ + # delete an entire source tree along with its builds: + project_up_to_date hash "$tree" badhash "$datadir" \ + "$configdir/$tree" "$mdir" || \ + x_ rm -Rf "src/$project/$tree" "elf/$project/$tree" + + x_ cp "$xbtmp/new.hash" "$XBMK_CACHE/hash/$project$tree" + + if singletree "$project" || [ -z "$target" ] || [ "$target" = "$tree" ] + then + return 0 + fi + + # delete only the builds of a given target, but not src. + # this is useful when only the target config changes, for + # example x200_8mb coreboot configs change, but not coreboot: + + project_up_to_date tghash "$target" badtghash "$configdir/$target" || \ + x_ rm -Rf "elf/$project/$tree/$target" + + x_ cp "$xbtmp/new.hash" "$XBMK_CACHE/tghash/$project$target" +} + +project_up_to_date() +{ + eval "`newvar hash old_hash`" + + hashdir="$1" + hashname="$2" + badhashvar="$3" + + shift 3 + + x_ mkdir -p "$XBMK_CACHE/$hashdir" + + if [ -f "$XBMK_CACHE/$hashdir/$project$hashname" ]; then + read -r old_hash < "$XBMK_CACHE/$hashdir/$project$hashname" \ + || err \ + "$hashdir: err '$XBMK_CACHE/$hashdir/$project$hashname'" \ + "project_up_to_date" "$hashdir" "$hashname" "$badhashvar" \ + "$@" + fi + + build_sbase + fx_ "x_ util/sbase/sha512sum" find "$@" -type f -not -path \ + "*/.git*/*" | awk '{print $1}' > "$xbtmp/tmp.hash" || \ + err "!h $project $hashdir" \ + "project_up_to_date" "$hashdir" "$hashname" "$badhashvar" "$@" + + hash="$(x_ "$sha512sum" "$xbtmp/tmp.hash" | awk '{print $1}' || \ + err)" || err "$hashname: Can't read sha512 of '$xbtmp/tmp.hash'" \ + "project_up_to_date" "$hashdir" "$hashname" "$badhashvar" "$@" + + if [ "$hash" != "$old_hash" ] || \ + [ ! -f "$XBMK_CACHE/$hashdir/$project$hashname" ]; then + eval "$badhashvar=\"y\"" + fi + + printf "%s\n" "$hash" > "$xbtmp/new.hash" || \ + err "!mkhash $xbtmp/new.hash ($hashdir $hashname $badhashvar)" \ + "project_up_to_date" "$hashdir" "$hashname" "$badhashvar" "$@" + + eval "[ \"\$$badhashvar\" = \"y\" ] && return 1"; : +} + +check_cross_compiler() +{ + cbdir="src/coreboot/$tree" + + [ "$project" != "coreboot" ] && \ + cbdir="src/coreboot/default" + [ -n "$xgcctree" ] && \ + cbdir="src/coreboot/$xgcctree" + + xfix="${1%-*}" + [ "$xfix" = "x86_64" ] && \ + xfix="x64" + + xgccfile="elf/coreboot/$tree/xgcc_${xfix}_was_compiled" + xgccargs="crossgcc-$xfix UPDATED_SUBMODULES=1 CPUS=$XBMK_THREADS" + + x_ ./mk -f coreboot "${cbdir#src/coreboot/}" + x_ mkdir -p "elf/coreboot/$tree" # TODO: is this needed? + + # tell build systems what cross-compiler to use + export PATH="$xbmkpwd/$cbdir/util/crossgcc/xgcc/bin:$PATH" + export CROSS_COMPILE="${xarch% *}-" # used by e.g. u-boot + + # coreboot-specific (we disable gnat on some trees) + [ -n "$xlang" ] && \ + export BUILD_LANGUAGES="$xlang" + + [ -f "$xgccfile" ] && \ + return 0 # build exists already, so skip building + + check_gnu_path gcc gnat || x_ check_gnu_path gnat gcc + make -C "$cbdir" $xgccargs || x_ make -C "$cbdir" $xgccargs + + x_ touch "$xgccfile" # prevent unnecessary re-build operations + remkdir "$xbtmp/gnupath" # reset hostcc +} + +# fix mismatching gcc/gnat versions on debian trixie/sid. as of december 2024, +# trixie/sid had gnat-13 as gnat and gcc-14 as gcc, but has gnat-14 in apt. in +# some cases, gcc 13+14 and gnat-13 are present; or gnat-14 and gcc-14, but +# gnat in PATH never resolves to gnat-14, because gnat-14 was "experimental" + +check_gnu_path() +{ + command -v "$1" 1>/dev/null || \ + err "Host '$1' unavailable" "check_gnu_path" "$@" + + eval "`newvar gccdir gccfull gccver gnatdir gnatfull gnatver`" + + if host_gcc_gnat_match "$@"; then + return 0 + elif ! match_gcc_gnat_versions "$@"; then + return 1 + fi +} + +# check if gcc/gnat versions already match: + +host_gcc_gnat_match() +{ + gnu_setver "$1" "$1" || \ + err "Command '$1' unavailable." "check_gnu_path" "$@" + gnu_setver "$2" "$2" || : + + eval "[ -z \"\$$1ver\" ] && err \"Cannot detect host '$1' version\"" + + [ "$gnatfull" != "$gccfull" ] && \ + return 1; : # mismatched gcc/gnat versions +} + +# find all gcc/gnat versions, matching them up in PATH: + +match_gcc_gnat_versions() +{ + eval "$1dir=\"$(dirname "$(command -v "$1")")\"" + eval "_gnudir=\"\$$1dir\"" + eval "_gnuver=\"\$$1ver\"" + + for _bin in "$_gnudir/$2-"*; do + if [ "${_bin#"$_gnudir/$2-"}" = "$_gnuver" ] && [ -x "$_bin" ] + then + _gnuver="${_bin#"$_gnudir/$2-"}" + break + fi + done + + gnu_setver "$2" "$_gnudir/$2-$_gnuver" || \ + return 1 + [ "$gnatfull" != "$gccfull" ] && \ + return 1 + + ( link_gcc_gnat_versions "$@" "$_gnudir" "$_gnuver" ) || \ + err "Can't link '$2-$_gnuver' '$_gnudir'" "check_gnu_path" "$@"; : +} + +# create symlinks in PATH, so that the GCC/GNAT versions match: + +link_gcc_gnat_versions() +{ + _gnudir="$3" + _gnuver="$4" + + remkdir "$xbtmp/gnupath" + + x_ cd "$xbtmp/gnupath" + + for _gnubin in "$_gnudir/$2"*"-$_gnuver" + do + _gnuutil="${_gnubin##*/}" + [ -e "$_gnubin" ] && \ + x_ ln -s "$_gnubin" "${_gnuutil%"-$_gnuver"}"; : + done +} + +# get the gcc/gnat version +# fail: return 1 if util not found +gnu_setver() +{ + eval "$2 --version 1>/dev/null 2>/dev/null || return 1" + + eval "$1ver=\"`"$2" --version 2>/dev/null | head -n1`\"" + eval "$1ver=\"\${$1ver##* }\"" + eval "$1full=\"\$$1ver\"" + eval "$1ver=\"\${$1ver%%.*}\""; : +} + +check_defconfig() +{ + [ ! -f "$defconfig" ] && \ + $if_not_dry_build \ + err "$project/$target: no config" check_defconfig "$@" + + dest_dir="$elfdir/$tree/$target/${defconfig#"$target_dir/config/"}" + + # skip build if a previous one exists: + + $if_dry_build \ + return 0 + elfcheck || \ + return 1; : +} + +elfcheck() +{ + # TODO: *STILL* very hacky check. do it properly (based on build.list) + + ( fx_ "eval exit 1 && err" find "$dest_dir" -type f ) || return 1; : +} + +handle_makefile() +{ + if $if_not_dry_build check_makefile "$srcdir"; then + $if_not_dry_build \ + x_ make -C "$srcdir" $cleanargs clean + fi + + [ -f "$defconfig" ] && \ + x_ cp "$defconfig" "$srcdir/.config" + + run_make_command || \ + err "no makefile!" "handle_makefile" "$@" + + _copy=".config" + + [ "$mode" = "savedefconfig" ] && \ + _copy="defconfig" + + [ "${mode%config}" != "$mode" ] && \ + $if_not_dry_build \ + x_ cp "$srcdir/$_copy" "$defconfig"; : + + [ -e "$srcdir/.git" ] && [ "$project" = "u-boot" ] && \ + [ "$mode" = "distclean" ] && \ + $if_not_dry_build \ + x_ git -C "$srcdir" $cleanargs clean -fdx; : +} + +run_make_command() +{ + [ -z "$mode" ] && \ + x_ $premake + + $if_not_dry_build check_cmake "$srcdir" && \ + [ -z "$mode" ] && \ + $if_not_dry_build \ + check_autoconf "$srcdir" + + $if_not_dry_build check_makefile "$srcdir" || \ + return 1 + + $if_not_dry_build \ + x_ make -C "$srcdir" $mode -j$XBMK_THREADS $makeargs + + [ -z "$mode" ] && \ + x_ $mkhelper + + check_makefile "$srcdir" || \ + return 0 + + [ "$mode" = "clean" ] || \ + return 0 + $if_dry_build \ + return 0 + + make -C "$srcdir" $cleanargs distclean || \ + x_ make -C "$srcdir" $cleanargs clean; : +} + +check_cmake() +{ + $if_dry_build \ + return 0 + [ ! -n "$cmakedir" ] && \ + return 0 + + check_makefile "$1" || \ + cmake -B "$1" "$1/$cmakedir" || \ + x_ check_makefile "$1" + + x_ check_makefile "$1"; : +} + +check_autoconf() +{ + ( + x_ cd "$1" + + [ -f "bootstrap" ] && \ + x_ ./bootstrap $bootstrapargs + [ -f "autogen.sh" ] && \ + x_ ./autogen.sh $autogenargs + [ -f "configure" ] && \ + x_ ./configure $autoconfargs; : + + ) || err "can't bootstrap project: $1" "check_autoconf" "$@"; : +} + +check_makefile() +{ + [ ! -f "$1/Makefile" ] && [ ! -f "$1/makefile" ] && \ + [ ! -f "$1/GNUmakefile" ] && \ + return 1; : +} + +copy_elf() +{ + [ -f "$listfile" ] && \ + x_ mkdir -p "$dest_dir" + + if [ -f "$listfile" ]; then + while read -r f; do + [ -f "$srcdir/$f" ] && \ + x_ cp "$srcdir/$f" "$dest_dir"; : + + done < "$listfile" || err \ + "cannot read '$listfile'" "copy_elf" "$@"; : + fi + + ( x_ make clean -C "$srcdir" $cleanargs ) || \ + err "can't make-clean '$srcdir'" "copy_elf" "$@"; : +} diff --git a/include/mrc.sh b/include/mrc.sh deleted file mode 100644 index 10d7e437..00000000 --- a/include/mrc.sh +++ /dev/null @@ -1,69 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -# Logic based on util/chromeos/crosfirmware.sh in coreboot cfc26ce278. -# Modifications in this version are Copyright 2021,2023-2025 Leah Rowe. -# Original copyright detailed in repo: https://review.coreboot.org/coreboot/ - -eval "`newvar MRC_board MRC_hash MRC_url MRC_url_bkup SHELLBALL`" - -extract_refcode() -{ - extract_mrc - - # cbfstool after coreboot 4.13 changed the stage file attribute scheme, - # and refcode is extracted from an image using the old scheme. we use - # cbfstool from coreboot 4.11_branch, the tree used by ASUS KGPE-D16: - - [ -z "$cbfstoolref" ] && \ - err "cbfstoolref not set" "extract_refcode" "$@" - - x_ mkdir -p "${_pre_dest%/*}" - - x_ "$cbfstoolref" "$appdir/bios.bin" extract \ - -m x86 -n fallback/refcode -f "$appdir/ref" -r RO_SECTION - - # enable the Intel GbE device, if told by offset MRC_refcode_gbe - [ -n "$MRC_refcode_gbe" ] && \ - x_ dd if="config/ifd/hp820g2/1.bin" of="$appdir/ref" bs=1 \ - seek=$MRC_refcode_gbe count=1 conv=notrunc; : - - x_ mv "$appdir/ref" "$_pre_dest" -} - -extract_mrc() -{ - [ -z "$MRC_board" ] && \ - err "MRC_board unset" "extract_mrc" "$@" - [ -z "$CONFIG_MRC_FILE" ] && \ - err "CONFIG_MRC_FILE unset" "extract_mrc" "$@" - - SHELLBALL="chromeos-firmwareupdate-$MRC_board" - - ( - x_ cd "$appdir" - extract_partition "${MRC_url##*/}" - extract_archive "$SHELLBALL" . - - ) || err "mrc download/extract failure" "extract_mrc" "$@" - - x_ "$cbfstool" "$appdir/"bios.bin extract -n mrc.bin \ - -f "${_pre_dest%/*}/mrc.bin" -r RO_SECTION -} - -extract_partition() -{ - printf "Extracting ROOT-A partition\n" - - ROOTP=$( printf "unit\nB\nprint\nquit\n" | \ - parted "${1%.zip}" 2>/dev/null | grep "ROOT-A" ) - - START=$(( $( echo $ROOTP | cut -f2 -d\ | tr -d "B" ) )) - SIZE=$(( $( echo $ROOTP | cut -f4 -d\ | tr -d "B" ) )) - - x_ dd if="${1%.zip}" of="root-a.ext2" bs=1024 \ - skip=$(( $START / 1024 )) count=$(( $SIZE / 1024 )) - - printf "cd /usr/sbin\ndump chromeos-firmwareupdate %s\nquit" \ - "$SHELLBALL" | debugfs "root-a.ext2" || \ - err "!extract shellball" "extract_partition" "$@" -} diff --git a/include/release.sh b/include/release.sh deleted file mode 100644 index f0dc4864..00000000 --- a/include/release.sh +++ /dev/null @@ -1,115 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-or-later - -# Copyright (c) 2023-2026 Leah Rowe - -eval "`newvar reldest reldir relmode rsrc vdir`" - -release() -{ - export XBMK_RELEASE="y" - reldir="release" - - while getopts m: option - do - [ -z "$OPTARG" ] && \ - err "empty argument not allowed" "release" "$@" - [ "$option" != "m" ] && \ - err "invalid option '-$option'" "release" "$@" - - relmode="$OPTARG" - done - - reldest="$reldir/$version" - [ -e "$reldest" ] && \ - err "already exists: \"$reldest\"" "release" "$@" - - vdir="`mktemp -d || err "can't make vdir"`" || \ - err "can't make tmp vdir" "release" "$@" - vdir="$vdir/$version" - rsrc="$vdir/${relname}_src" - - remkdir "$vdir" - x_ git clone . "$rsrc" - update_xbmkver "$rsrc" - - prep_release src - prep_release tarball - [ "$relmode" != "src" ] && \ - prep_release bin - - x_ rm -Rf "$rsrc" - - x_ mkdir -p "$reldir" - x_ mv "$vdir" "$reldir" - x_ rm -Rf "${vdir%"/$version"}" - - printf "\n\nDONE! Check release files under %s\n" "$reldest" -} - -prep_release() -{ - ( - if [ "$1" != "tarball" ]; then - x_ cd "$rsrc" - [ ! -e "cache" ] && \ - x_ ln -s "$XBMK_CACHE" "cache"; : - fi - - prep_release_$1 - - ) || err "can't prep release $1" "prep_release" "$@" -} - -prep_release_src() -{ - x_ cp -R "util/sbase" "util/sbase2" - - x_ ./mk -f - - fx_ "x_ rm -Rf" x_ find . -name ".git" - fx_ "x_ rm -Rf" x_ find . -name ".gitmodules" - - ( fx_ nuke x_ find config -type f -name "nuke.list" ) || \ - err "can't prune project files" "prep_release_src" "$@"; : -} - -nuke() -{ - r="$rsrc/src/${1#config/}" - - if [ -d "${r%/*}" ]; then - x_ cd "${r%/*}" - dx_ "x_ rm -Rf" "$rsrc/$1" - fi -} - -prep_release_tarball() -{ - git log --graph --pretty=format:'%Cred%h%Creset %s %Creset' \ - --abbrev-commit > "$rsrc/CHANGELOG" || \ - err "can't create '$rsrc/CHANGELOG'" "prep_release_tarball" "$@" - - x_ rm -f "$rsrc/lock" "$rsrc/cache" - x_ rm -Rf "$rsrc/xbmkwd" "$rsrc/util/sbase" - x_ mv "$rsrc/util/sbase2" "$rsrc/util/sbase" - - ( - x_ cd "${rsrc%/*}" - x_ mktarball "${rsrc##*/}" "${rsrc##*/}.tar.xz" - - ) || err "can't create src tarball" "prep_release_tarball" "$@"; : -} - -prep_release_bin() -{ - x_ ./mk -d coreboot - - x_ ./mk -b coreboot - x_ ./mk -b pico-serprog - x_ ./mk -b stm32-vserprog - x_ ./mk -b pcsx-redux - - fx_ mkrom_tarball x_ find bin -maxdepth 1 -type d -name "serprog_*" - - x_ mv bin ../roms -} diff --git a/include/rom.sh b/include/rom.sh deleted file mode 100644 index adaac8a0..00000000 --- a/include/rom.sh +++ /dev/null @@ -1,459 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-or-later - -# Copyright (c) 2014-2016,2020-2021,2023-2025 Leah Rowe -# Copyright (c) 2021-2022 Ferass El Hafidi -# Copyright (c) 2022 Caleb La Grange -# Copyright (c) 2022-2023 Alper Nebi Yasak -# Copyright (c) 2023-2024 Riku Viitanen - -grubdata="config/data/grub" - -buildser() -{ - if [ "$1" = "pico" ]; then - x_ cmake -DPICO_BOARD="$2" \ - -DPICO_SDK_PATH="$picosdk" -B "$sersrc/build" "$sersrc" - x_ cmake --build "$sersrc/build" - elif [ "$1" = "stm32" ]; then - x_ make -C "$sersrc" libopencm3-just-make BOARD=$2 - x_ make -C "$sersrc" BOARD=$2 - fi - - x_ mkdir -p "bin/serprog_$1" - x_ mv "$serx" "bin/serprog_$1/serprog_$2.${serx##*.}" -} - -copyps1bios() -{ - $if_dry_build \ - return 0 - - remkdir "bin/playstation" - x_ cp src/pcsx-redux/src/mips/openbios/openbios.bin bin/playstation - - printf "MIT License\n\nCopyright (c) 2019-2025 PCSX-Redux authors\n\n" \ - > bin/playstation/COPYING.txt || \ - err "can't write PCSX Redux copyright info" "copyps1bios" "$@" - - x_ cat config/snippet/mit >>bin/playstation/COPYING.txt || \ - err "can't copy MIT license snippet" "copyps1bios" "$@" -} - -mkpayload_grub() -{ - eval "`newvar grub_modules grub_install_modules`" - - $if_dry_build \ - return 0 - - . "$grubdata/module/$tree" || \ - err "Can't read '$grubdata/module/$tree'" "mkpayload_grub" "$@" - - x_ rm -f "$srcdir/grub.elf" - - x_ "$srcdir/grub-mkstandalone" \ - --grub-mkimage="$srcdir/grub-mkimage" \ - -O i386-coreboot -o "$srcdir/grub.elf" -d "${srcdir}/grub-core/" \ - --fonts= --themes= --locales= --modules="$grub_modules" \ - --install-modules="$grub_install_modules" \ - "/boot/grub/grub_default.cfg=${srcdir}/.config" \ - "/boot/grub/grub.cfg=$grubdata/memdisk.cfg"; : -} - -corebootpremake() -{ - [ "$XBMK_RELEASE" = "y" ] && [ "$release" = "n" ] && \ - return 0 - - $if_not_dry_build \ - cook_coreboot_config - - fx_ check_coreboot_util printf "cbfstool\nifdtool\n" - - printf "%s\n" "${version%%-*}" > "$srcdir/.coreboot-version" || \ - err "!mk $srcdir .coreboot-version" "corebootpremake" "$@" - - [ -z "$mode" ] && [ "$target" != "$tree" ] && \ - x_ ./mk download "$target"; : -} - -cook_coreboot_config() -{ - if [ -z "$mode" ] && [ -f "$srcdir/.config" ]; then - printf "CONFIG_CCACHE=y\n" >> "$srcdir/.config" || \ - err "can't cook '$srcdir'" "cook_coreboot_config" "$@" - fi -} - -check_coreboot_util() -{ - [ "$badhash" = "y" ] && \ - x_ rm -f "elf/coreboot/$tree/$1" - if e "elf/coreboot/$tree/$1" f; then - return 0 - fi - - utilelfdir="elf/coreboot/$tree" - utilsrcdir="src/coreboot/$tree/util/$1" - - utilmode="" - [ -n "$mode" ] && \ - utilmode="clean" - - x_ make -C "$utilsrcdir" $utilmode -j$XBMK_THREADS $makeargs - - if [ -n "$mode" ]; then - x_ rm -Rf "$utilelfdir" - return 0 - elif [ -n "$mode" ] || [ -f "$utilelfdir/$1" ]; then - return 0 - fi - - x_ mkdir -p "$utilelfdir" - x_ cp "$utilsrcdir/$1" "$utilelfdir" - - [ "$1" = "cbfstool" ] && \ - x_ cp "$utilsrcdir/rmodtool" "$utilelfdir"; : -} - -coreboot_pad_one_byte() -{ - [ "$XBMK_RELEASE" = "y" ] && [ "$release" = "n" ] && \ - return 0 - - $if_not_dry_build \ - pad_one_byte "$srcdir/build/coreboot.rom" -} - -mkcorebootbin() -{ - [ "$XBMK_RELEASE" = "y" ] && [ "$release" = "n" ] && \ - return 0 - - $if_not_dry_build \ - check_coreboot_util cbfstool - - $if_not_dry_build \ - check_coreboot_util ifdtool - - for y in "$target_dir/config"/*; do - defconfig="$y" - mkcorebootbin_real - done - - mkcoreboottar -} - -mkcorebootbin_real() -{ - [ "$target" = "$tree" ] && \ - return 0 - - tmprom="$xbtmp/coreboot.rom" - - initmode="${defconfig##*/}" - displaymode="${initmode##*_}" - if [ "$displaymode" = "$initmode" ]; then - # blank it for "normal" or "fspgop" configs: - - displaymode="" - fi - initmode="${initmode%%_*}" - cbfstool="elf/coreboot/$tree/cbfstool" - - # cbfstool option backends, if they exist - cbfscfg="config/coreboot/$target/cbfs.cfg" - - elfrom="elf/coreboot/$tree/$target/$initmode" - [ -n "$displaymode" ] && \ - elfrom="${elfrom}_$displaymode" - elfrom="$elfrom/coreboot.rom" - - $if_not_dry_build \ - x_ cp "$elfrom" "$tmprom" - - $if_not_dry_build \ - unpad_one_byte "$tmprom" - - [ -n "$payload_uboot" ] && [ "$payload_uboot" != "amd64" ] && \ - [ "$payload_uboot" != "i386" ] && [ "$payload_uboot" != "arm64" ] \ - && err "'$target' defines bad u-boot type '$payload_uboot'" \ - "mkcorebootbin_real" "$@" - - [ -n "$payload_uboot" ] && [ "$payload_uboot" != "arm64" ] && \ - payload_seabios="y" - - [ -z "$uboot_config" ] && \ - uboot_config="default" - [ "$payload_grub" = "y" ] && \ - payload_seabios="y" - [ "$payload_seabios" = "y" ] && [ "$payload_uboot" = "arm64" ] && \ - $if_not_dry_build \ - err "$target: U-Boot arm / SeaBIOS/GRUB both enabled" \ - "mkcorebootbin_real" "$@" - - [ -z "$grub_scan_disk" ] && \ - grub_scan_disk="nvme ahci ata" - [ -z "$grubtree" ] && \ - grubtree="default" - grubelf="elf/grub/$grubtree/$grubtree/payload/grub.elf" - - [ "$payload_memtest" != "y" ] && \ - payload_memtest="n" - [ "$(uname -m)" != "x86_64" ] && \ - payload_memtest="n" - - [ "$payload_grubsea" = "y" ] && [ "$initmode" = "normal" ] && \ - payload_grubsea="n" - [ "$payload_grub" != "y" ] && \ - payload_grubsea="n" - - $if_dry_build \ - return 0 - - [ -f "$cbfscfg" ] && \ - dx_ add_cbfs_option "$cbfscfg" - - if grep "CONFIG_PAYLOAD_NONE=y" "$defconfig"; then - if [ "$payload_seabios" = "y" ]; then - pname="seabios" - add_seabios - fi - if [ "$payload_uboot" = "arm64" ]; then - pname="uboot" - add_uboot - fi - else - pname="custom" - cprom - fi; : -} - -# options for cbfs backend (as opposed to nvram/smmstore): - -add_cbfs_option() -{ - op_name="`printf "%s\n" "$1" | awk '{print $1}'`" - op_arg="`printf "%s\n" "$1" | awk '{print $2}'`" - - if [ -z "$op_name" ] || [ -z "$op_arg" ]; then - return 0 - fi - - ( x_ "$cbfstool" "$tmprom" remove -n "option/$op_name" 1>/dev/null \ - 2>/dev/null ) || : - - x_ "$cbfstool" "$tmprom" add-int -i "$op_arg" -n "option/$op_name" -} - -# in our design, SeaBIOS is also responsible for starting either -# a GRUB or U-Boot payload. this is because SeaBIOS is generally -# a more reliable codebase, so it's less likely to cause a brick -# during testing and development, or user configuration. if one -# of the u-boot or grub payloads fails, the user still has a -# functional SeaBIOS setup to fall back on. watch: - -add_seabios() -{ - [ -n "$payload_uboot" ] && [ "$payload_uboot" != "arm64" ] && \ - $if_not_dry_build \ - add_uboot # add u-boot first, due to fixed cbfs offset - - _seabioself="elf/seabios/default/default/$initmode/bios.bin.elf" - [ "$initmode" = "fspgop" ] && \ - _seabioself="elf/seabios/default/default/libgfxinit/bios.bin.elf" - - _seaname="fallback/payload" - [ "$payload_grubsea" = "y" ] && \ - _seaname="seabios.elf" - - cbfs "$tmprom" "$_seabioself" "$_seaname" - - x_ "$cbfstool" "$tmprom" add-int -i 3000 -n etc/ps2-keyboard-spinup - - opexec="2" - [ "$initmode" = "vgarom" ] && \ - opexec="0" - x_ "$cbfstool" "$tmprom" add-int -i $opexec -n etc/pci-optionrom-exec - - x_ "$cbfstool" "$tmprom" add-int -i 0 -n etc/optionroms-checksum - if [ "$initmode" = "libgfxinit" ] || [ "$initmode" = "fspgop" ]; then - cbfs "$tmprom" "$seavgabiosrom" vgaroms/seavgabios.bin raw - fi - - [ "$payload_memtest" = "y" ] && \ - cbfs "$tmprom" "elf/memtest86plus/memtest.bin" img/memtest - - [ "$payload_grub" = "y" ] && \ - add_grub - - [ "$payload_grubsea" != "y" ] && \ - cprom # seabios, but don't load grub/u-boot first - - # now make seauboot(u-boot loaded by seabios) and SeaGRUB (GRUB loaded - # by SeaBIOS) images; users can bypass via ESC to boot from SeaBIOS - - if [ "$payload_uboot" = "amd64" ] && \ - [ "$displaymode" != "txtmode" ] && \ - [ "$initmode" != "normal" ] && [ "$payload_grubsea" != "y" ]; then - pname="seauboot" - cprom "seauboot" - fi - - if [ "$payload_grub" = "y" ]; then - pname="seagrub" - mkseagrub - fi -} - -add_grub() -{ - # path in CBFS for the GRUB payload - _grubname="img/grub2" - [ "$payload_grubsea" = "y" ] && \ - _grubname="fallback/payload" - - cbfs "$tmprom" "$grubelf" "$_grubname" - - printf "set grub_scan_disk=\"%s\"\n" "$grub_scan_disk" \ - > "$xbtmp/tmpcfg" || \ - err "$target: !insert scandisk" "add_grub" "$@" - - cbfs "$tmprom" "$xbtmp/tmpcfg" scan.cfg raw - - [ "$initmode" != "normal" ] && [ "$displaymode" != "txtmode" ] && \ - cbfs "$tmprom" "$grubdata/background/background1280x800.png" \ - "background.png" raw; : -} - -mkseagrub() -{ - if [ "$payload_grubsea" = "y" ]; then - pname="grub" - else - cbfs "$tmprom" "$grubdata/bootorder" bootorder raw - fi - - fx_ cprom x_ find "$grubdata/keymap" -type f -name "*.gkb" -} - -add_uboot() -{ - if [ "$displaymode" = "txtmode" ]; then - printf "cb/%s: Can't use U-Boot in text mode\n" "$target" 1>&2 - return 0 - elif [ "$initmode" = "normal" ]; then - printf "cb/%s: Can't use U-Boot in normal initmode\n" \ - "$target" 1>&2 - return 0 - fi - - # TODO: re-work to allow each coreboot target to say which ub tree - # instead of hardcoding as in the current logic below: - - # aarch64 targets: - ubcbfsargs="" - ubpath="fallback/payload" - ubtree="default" - ubtarget="$target" - - # override for x86/x86_64 targets: - if [ -n "$payload_uboot" ] && [ "$payload_uboot" != "arm64" ]; then - ubcbfsargs="-l 0x1110000 -e 0x1110000" # 64-bit and 32-bit - # on 64-bit, 0x1120000 is the SPL, with a stub that - # loads it, located at 0x1110000 - - ubpath="img/u-boot" # 64-bit - ubtree="x86_64" - ubtarget="amd64coreboot" - - if [ "$payload_uboot" = "i386" ]; then - ubpath="u-boot" # 32-bit - ubtree="x86" - ubtarget="i386coreboot"; : - fi - fi - - ubdir="elf/u-boot/$ubtree/$ubtarget/$uboot_config" - - ubootelf="$ubdir/u-boot.elf" # aarch64 - [ ! -f "$ubootelf" ] && \ - ubootelf="$ubdir/u-boot" # aarch64 (fallback) - [ "$payload_uboot" = "i386" ] && \ - ubootelf="$ubdir/u-boot-dtb.bin" # x86 override - [ "$payload_uboot" = "amd64" ] && \ - ubootelf="$ubdir/u-boot-x86-with-spl.bin" # x86_64 override - - cbfs "$tmprom" "$ubootelf" "$ubpath" $ubcbfsargs - [ "$payload_seabios" != "y" ] && \ - cprom; : -} - -# prepare the final image in bin/ for user installation: - -cprom() -{ - cpcmd="cp" - - tmpnew="" - newrom="bin/$target/${pname}_${target}_$initmode.rom" - - [ -n "$displaymode" ] && \ - newrom="${newrom%.rom}_$displaymode.rom" - if [ $# -gt 0 ] && [ "${1%.gkb}" != "$1" ]; then - tmpnew="${1##*/}" - newrom="${newrom%.rom}_${tmpnew%.gkb}.rom" - fi - - irom="$tmprom" - - if [ $# -gt 0 ]; then - irom="$(mktemp || err "!mk irom, $(echo "$@")")" || \ - err "can't copy rom" "cprom" "$@" - - x_ cp "$tmprom" "$irom" && cpcmd="mv" - - if [ "${1%.gkb}" != "$1" ]; then - cbfs "$irom" "$grubdata/keymap/$tmpnew" keymap.gkb raw - elif [ "$1" = "seauboot" ]; then - cbfs "$irom" "$grubdata/bootorder_uboot" bootorder raw - fi - fi - - printf "Creating new %s image: '%s'\n" "$projectname" "$newrom" - - x_ mkdir -p "bin/$target" - x_ $cpcmd "$irom" "$newrom" -} - -cbfs() -{ - ccmd="add-payload" - lzma="-c lzma" - - if [ $# -gt 3 ] && [ $# -lt 5 ]; then - ccmd="add" - lzma="-t $4" - elif [ $# -gt 4 ] && [ "$5" = "0x1110000" ]; then - ccmd="add-flat-binary" && \ - lzma="-c lzma -l 0x1110000 -e 0x1110000" - fi - - x_ "$cbfstool" "$1" $ccmd -f "$2" -n "$3" $lzma -} - -# for release files: - -mkcoreboottar() -{ - $if_dry_build \ - return 0 - - if [ "$target" = "$tree" ] || [ "$XBMK_RELEASE" != "y" ] || \ - [ "$release" = "n" ]; then - return 0 - fi - - mkrom_tarball "bin/$target" - x_ ./mk inject "bin/${relname}_${target}.tar.xz" nuke -} diff --git a/include/tree.sh b/include/tree.sh deleted file mode 100644 index 434796e2..00000000 --- a/include/tree.sh +++ /dev/null @@ -1,628 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-or-later - -# Copyright (c) 2022-2023 Alper Nebi Yasak -# Copyright (c) 2022 Ferass El Hafidi -# Copyright (c) 2023-2025 Leah Rowe - -# flag e.g. ./mk -b <-- mkflag would be "b" -flag="" - -# macros, overridden depending on the flag -if_do_make="" -if_dry_build=":" -if_not_do_make=":" -if_not_dry_build="" - -eval "`newvar autoconfargs autogenargs badhash badtghash bootstrapargs \ - build_depend buildtype cleanargs cmakedir cmd defconfig dest_dir elfdir \ - forcepull gccdir gccfull gccver gnatdir gnatfull gnatver listfile \ - makeargs mdir mkhelper mkhelpercfg mode postmake premake project release \ - rev srcdir target target_dir targets tree xarch xgcctree xlang`" - -trees() -{ - flags="f:F:b:m:u:c:x:s:l:n:d:" - - while getopts $flags option - do - [ -n "$flag" ] && \ - err "only one flag is permitted" "trees" "$@" - - flag="$1" - - # the "mode" variable is affixed to a make command, example: - # ./mk -m coreboot does: make menuconfig -C src/coreboot/tree - - case "$flag" in - -d) - # -d is similar to -b, except that - # a large number of operations will be - # skipped. these are "if_not_dry_build build" scenarios - # where only a subset of build tasks are done, - # and $if_not_dry_build is prefixed to skipped commands - - if_dry_build="" - if_not_dry_build=":" - ;; - -b) : ;; - -u) mode="oldconfig" ;; - -m) mode="menuconfig" ;; - -c) mode="distclean" ;; - -x) mode="crossgcc-clean" ;; - -f|-F) # download source code for a project - # macros. colon means false. - if_do_make=":" - if_dry_build="" - if_not_do_make="" - if_not_dry_build=":" - [ "$flag" = "-F" ] && \ - forcepull="y"; : # never skip git fetch/pull - ;; - -s) mode="savedefconfig" ;; - -l) mode="olddefconfig" ;; - -n) mode="nconfig" ;; - *) err "invalid option '-$option'" "trees" "$@" ;; - esac - - if [ -z "${OPTARG+x}" ]; then - shift 1 - break - fi - - project="${OPTARG#src/}" - project="${project#config/git/}" - - shift 2 - done - - if [ -z "$flag" ]; then - err "missing flag ($flags)" "trees" "$@" - elif [ -z "$project" ]; then - fx_ "x_ ./mk $flag" x_ ls -1 config/git - return 1 - elif [ ! -f "config/git/$project/pkg.cfg" ]; then - err "config/git/$project/pkg.cfg missing" "trees" "$@" - fi - - elfdir="elf/$project" - datadir="config/data/$project" - configdir="config/$project" - srcdir="src/$project" - dest_dir="$elfdir" - - listfile="$datadir/build.list" - [ ! -f "$listfile" ] && \ - listfile="" # build.list is optional on all projects - - mkhelpercfg="$datadir/mkhelper.cfg" - if e "$mkhelpercfg" f missing; then - mkhelpercfg="$xbtmp/mkhelper.cfg" - x_ touch "$mkhelpercfg" - fi - - targets="$*" - cmd="build_targets $targets" - if singletree "$project"; then - cmd="build_project" - fi - - remkdir "${tmpgit%/*}" -} - -build_project() -{ - configure_project "$configdir" || \ - return 0 - - [ ! -f "$listfile" ] || \ - $if_not_dry_build elfcheck || \ - return 0 - - [ "$mode" = "distclean" ] && \ - mode="clean" - - run_make_command || \ - return 0 - - [ -z "$mode" ] && \ - $if_not_dry_build \ - copy_elf; : -} - -build_targets() -{ - if [ ! -d "$configdir" ]; then - err "directory '$configdir' doesn't exist" "build_targets" "$@" - elif [ $# -lt 1 ]; then - targets="$(ls -1 "$configdir")" || \ - err "'$configdir': can't list targets" "build_targets" "$@" - fi - - for x in $targets - do - unset CROSS_COMPILE - export PATH="$xbmkpath" - - if [ "$x" = "list" ]; then - x_ ls -1 "config/$project" - listfile="" - break - fi - - printf "'make %s', '%s', '%s'\n" "$mode" "$project" "$x" - - target="$x" - - x_ handle_defconfig - - [ -z "$mode" ] && \ - x_ $postmake; : - done; : -} - -handle_defconfig() -{ - target_dir="$configdir/$target" - - [ ! -f "CHANGELOG" ] && \ - fetch_project "$project" - - configure_project "$target_dir" || \ - return 0 - - [ -z "$tree" ] && \ - err "$configdir: 'tree' not set" "handle_defconfig" "$@" - - srcdir="src/$project/$tree" - - [ "$mode" = "${mode%clean}" ] && [ ! -d "$srcdir" ] && \ - return 0 - - for y in "$target_dir/config"/* - do - [ "$flag" != "-d" ] && [ ! -f "$y" ] && \ - continue - [ "$flag" != "-d" ] && \ - defconfig="$y" - - if [ -z "$mode" ]; then - check_defconfig || continue; : - fi - - [ -z "$mode" ] && \ - for _xarch in $xarch; do - $if_dry_build \ - break - [ -n "$_xarch" ] && \ - check_cross_compiler "$_xarch"; : - done; : - - handle_makefile - - [ -z "$mode" ] && \ - $if_not_dry_build \ - copy_elf; : - done; : -} - -configure_project() -{ - _tcfg="$1/target.cfg" - - eval "`newvar autoconfargs badhash badtghash bootstrapargs \ - build_depend buildtype cleanargs makeargs mkhelper postmake \ - premake release xarch xgcctree xlang`" - - [ ! -f "$_tcfg" ] && \ - buildtype="auto" - - # globally initialise all variables for a source tree / target: - if e "$datadir/mkhelper.cfg" f; then - . "$datadir/mkhelper.cfg" || \ - err "Can't read '$datadir/mkhelper.cfg'" \ - "configure_project" "$@" - fi - - # override target/tree specific variables from per-target config: - while e "$_tcfg" f || [ "$cmd" != "build_project" ] - do - printf "Loading %s config: %s\n" "$project" "$_tcfg" - eval "`newvar rev tree`" - - . "$_tcfg" || \ - err "Can't read '$_tcfg'" "configure_project" "$@" - - [ "$flag" = "-d" ] && \ - build_depend="" # dry run - - [ "$cmd" = "build_project" ] && \ - break # single-tree, so targeting is unnecessary - $if_do_make \ - break - [ "${_tcfg%/*/target.cfg}" = "${_tcfg%"/$tree/target.cfg"}" ] \ - && break # target and tree matching was successful - - _tcfg="${_tcfg%/*/target.cfg}/$tree/target.cfg" # try next - done - - [ "$XBMK_RELEASE" = "y" ] && [ "$release" = "n" ] && \ - return 1 - [ -n "$buildtype" ] && [ "${mode%config}" != "$mode" ] && \ - return 1 - - [ -z "$mode" ] && \ - $if_not_dry_build \ - build_dependencies - - mdir="$xbmkpwd/config/submodule/$project" - [ -n "$tree" ] && \ - mdir="$mdir/$tree" - - if [ ! -f "CHANGELOG" ]; then - delete_old_project_files - $if_not_do_make \ - fetch_${cmd#build_} - fi - $if_not_do_make \ - return 1 - - x_ ./mk -f "$project" "$target" -} - -# projects can specify which other projects -# to build first, as declared dependencies: - -build_dependencies() -{ - for bd in $build_depend - do - bd_project="${bd%%/*}" - bd_tree="${bd##*/}" - - [ -z "$bd_project" ] && \ - $if_not_dry_build \ - err "$project/$tree: !bd '$bd'" \ - "build_dependencies" "$@" - [ "${bd##*/}" = "$bd" ] && \ - bd_tree="" - [ -n "$bd_project" ] && \ - $if_not_dry_build \ - x_ ./mk -b $bd_project $bd_tree; : - done; : -} - -# delete_old_project_files along with project_up_to_date, -# concatenates the sha512sum hashes of all files related to -# a project, tree or target, then gets the sha512sum of that -# concatenation. this is checked against any existing -# calculation previously cached; if the result differs, or -# nothing was previously stored, we know to delete resources -# such as builds, project sources and so on, for auto-rebuild: - -delete_old_project_files() -{ - # delete an entire source tree along with its builds: - project_up_to_date hash "$tree" badhash "$datadir" \ - "$configdir/$tree" "$mdir" || \ - x_ rm -Rf "src/$project/$tree" "elf/$project/$tree" - - x_ cp "$xbtmp/new.hash" "$XBMK_CACHE/hash/$project$tree" - - if singletree "$project" || [ -z "$target" ] || [ "$target" = "$tree" ] - then - return 0 - fi - - # delete only the builds of a given target, but not src. - # this is useful when only the target config changes, for - # example x200_8mb coreboot configs change, but not coreboot: - - project_up_to_date tghash "$target" badtghash "$configdir/$target" || \ - x_ rm -Rf "elf/$project/$tree/$target" - - x_ cp "$xbtmp/new.hash" "$XBMK_CACHE/tghash/$project$target" -} - -project_up_to_date() -{ - eval "`newvar hash old_hash`" - - hashdir="$1" - hashname="$2" - badhashvar="$3" - - shift 3 - - x_ mkdir -p "$XBMK_CACHE/$hashdir" - - if [ -f "$XBMK_CACHE/$hashdir/$project$hashname" ]; then - read -r old_hash < "$XBMK_CACHE/$hashdir/$project$hashname" \ - || err \ - "$hashdir: err '$XBMK_CACHE/$hashdir/$project$hashname'" \ - "project_up_to_date" "$hashdir" "$hashname" "$badhashvar" \ - "$@" - fi - - build_sbase - fx_ "x_ util/sbase/sha512sum" find "$@" -type f -not -path \ - "*/.git*/*" | awk '{print $1}' > "$xbtmp/tmp.hash" || \ - err "!h $project $hashdir" \ - "project_up_to_date" "$hashdir" "$hashname" "$badhashvar" "$@" - - hash="$(x_ "$sha512sum" "$xbtmp/tmp.hash" | awk '{print $1}' || \ - err)" || err "$hashname: Can't read sha512 of '$xbtmp/tmp.hash'" \ - "project_up_to_date" "$hashdir" "$hashname" "$badhashvar" "$@" - - if [ "$hash" != "$old_hash" ] || \ - [ ! -f "$XBMK_CACHE/$hashdir/$project$hashname" ]; then - eval "$badhashvar=\"y\"" - fi - - printf "%s\n" "$hash" > "$xbtmp/new.hash" || \ - err "!mkhash $xbtmp/new.hash ($hashdir $hashname $badhashvar)" \ - "project_up_to_date" "$hashdir" "$hashname" "$badhashvar" "$@" - - eval "[ \"\$$badhashvar\" = \"y\" ] && return 1"; : -} - -check_cross_compiler() -{ - cbdir="src/coreboot/$tree" - - [ "$project" != "coreboot" ] && \ - cbdir="src/coreboot/default" - [ -n "$xgcctree" ] && \ - cbdir="src/coreboot/$xgcctree" - - xfix="${1%-*}" - [ "$xfix" = "x86_64" ] && \ - xfix="x64" - - xgccfile="elf/coreboot/$tree/xgcc_${xfix}_was_compiled" - xgccargs="crossgcc-$xfix UPDATED_SUBMODULES=1 CPUS=$XBMK_THREADS" - - x_ ./mk -f coreboot "${cbdir#src/coreboot/}" - x_ mkdir -p "elf/coreboot/$tree" # TODO: is this needed? - - # tell build systems what cross-compiler to use - export PATH="$xbmkpwd/$cbdir/util/crossgcc/xgcc/bin:$PATH" - export CROSS_COMPILE="${xarch% *}-" # used by e.g. u-boot - - # coreboot-specific (we disable gnat on some trees) - [ -n "$xlang" ] && \ - export BUILD_LANGUAGES="$xlang" - - [ -f "$xgccfile" ] && \ - return 0 # build exists already, so skip building - - check_gnu_path gcc gnat || x_ check_gnu_path gnat gcc - make -C "$cbdir" $xgccargs || x_ make -C "$cbdir" $xgccargs - - x_ touch "$xgccfile" # prevent unnecessary re-build operations - remkdir "$xbtmp/gnupath" # reset hostcc -} - -# fix mismatching gcc/gnat versions on debian trixie/sid. as of december 2024, -# trixie/sid had gnat-13 as gnat and gcc-14 as gcc, but has gnat-14 in apt. in -# some cases, gcc 13+14 and gnat-13 are present; or gnat-14 and gcc-14, but -# gnat in PATH never resolves to gnat-14, because gnat-14 was "experimental" - -check_gnu_path() -{ - command -v "$1" 1>/dev/null || \ - err "Host '$1' unavailable" "check_gnu_path" "$@" - - eval "`newvar gccdir gccfull gccver gnatdir gnatfull gnatver`" - - if host_gcc_gnat_match "$@"; then - return 0 - elif ! match_gcc_gnat_versions "$@"; then - return 1 - fi -} - -# check if gcc/gnat versions already match: - -host_gcc_gnat_match() -{ - gnu_setver "$1" "$1" || \ - err "Command '$1' unavailable." "check_gnu_path" "$@" - gnu_setver "$2" "$2" || : - - eval "[ -z \"\$$1ver\" ] && err \"Cannot detect host '$1' version\"" - - [ "$gnatfull" != "$gccfull" ] && \ - return 1; : # mismatched gcc/gnat versions -} - -# find all gcc/gnat versions, matching them up in PATH: - -match_gcc_gnat_versions() -{ - eval "$1dir=\"$(dirname "$(command -v "$1")")\"" - eval "_gnudir=\"\$$1dir\"" - eval "_gnuver=\"\$$1ver\"" - - for _bin in "$_gnudir/$2-"*; do - if [ "${_bin#"$_gnudir/$2-"}" = "$_gnuver" ] && [ -x "$_bin" ] - then - _gnuver="${_bin#"$_gnudir/$2-"}" - break - fi - done - - gnu_setver "$2" "$_gnudir/$2-$_gnuver" || \ - return 1 - [ "$gnatfull" != "$gccfull" ] && \ - return 1 - - ( link_gcc_gnat_versions "$@" "$_gnudir" "$_gnuver" ) || \ - err "Can't link '$2-$_gnuver' '$_gnudir'" "check_gnu_path" "$@"; : -} - -# create symlinks in PATH, so that the GCC/GNAT versions match: - -link_gcc_gnat_versions() -{ - _gnudir="$3" - _gnuver="$4" - - remkdir "$xbtmp/gnupath" - - x_ cd "$xbtmp/gnupath" - - for _gnubin in "$_gnudir/$2"*"-$_gnuver" - do - _gnuutil="${_gnubin##*/}" - [ -e "$_gnubin" ] && \ - x_ ln -s "$_gnubin" "${_gnuutil%"-$_gnuver"}"; : - done -} - -# get the gcc/gnat version -# fail: return 1 if util not found -gnu_setver() -{ - eval "$2 --version 1>/dev/null 2>/dev/null || return 1" - - eval "$1ver=\"`"$2" --version 2>/dev/null | head -n1`\"" - eval "$1ver=\"\${$1ver##* }\"" - eval "$1full=\"\$$1ver\"" - eval "$1ver=\"\${$1ver%%.*}\""; : -} - -check_defconfig() -{ - [ ! -f "$defconfig" ] && \ - $if_not_dry_build \ - err "$project/$target: no config" check_defconfig "$@" - - dest_dir="$elfdir/$tree/$target/${defconfig#"$target_dir/config/"}" - - # skip build if a previous one exists: - - $if_dry_build \ - return 0 - elfcheck || \ - return 1; : -} - -elfcheck() -{ - # TODO: *STILL* very hacky check. do it properly (based on build.list) - - ( fx_ "eval exit 1 && err" find "$dest_dir" -type f ) || return 1; : -} - -handle_makefile() -{ - if $if_not_dry_build check_makefile "$srcdir"; then - $if_not_dry_build \ - x_ make -C "$srcdir" $cleanargs clean - fi - - [ -f "$defconfig" ] && \ - x_ cp "$defconfig" "$srcdir/.config" - - run_make_command || \ - err "no makefile!" "handle_makefile" "$@" - - _copy=".config" - - [ "$mode" = "savedefconfig" ] && \ - _copy="defconfig" - - [ "${mode%config}" != "$mode" ] && \ - $if_not_dry_build \ - x_ cp "$srcdir/$_copy" "$defconfig"; : - - [ -e "$srcdir/.git" ] && [ "$project" = "u-boot" ] && \ - [ "$mode" = "distclean" ] && \ - $if_not_dry_build \ - x_ git -C "$srcdir" $cleanargs clean -fdx; : -} - -run_make_command() -{ - [ -z "$mode" ] && \ - x_ $premake - - $if_not_dry_build check_cmake "$srcdir" && \ - [ -z "$mode" ] && \ - $if_not_dry_build \ - check_autoconf "$srcdir" - - $if_not_dry_build check_makefile "$srcdir" || \ - return 1 - - $if_not_dry_build \ - x_ make -C "$srcdir" $mode -j$XBMK_THREADS $makeargs - - [ -z "$mode" ] && \ - x_ $mkhelper - - check_makefile "$srcdir" || \ - return 0 - - [ "$mode" = "clean" ] || \ - return 0 - $if_dry_build \ - return 0 - - make -C "$srcdir" $cleanargs distclean || \ - x_ make -C "$srcdir" $cleanargs clean; : -} - -check_cmake() -{ - $if_dry_build \ - return 0 - [ ! -n "$cmakedir" ] && \ - return 0 - - check_makefile "$1" || \ - cmake -B "$1" "$1/$cmakedir" || \ - x_ check_makefile "$1" - - x_ check_makefile "$1"; : -} - -check_autoconf() -{ - ( - x_ cd "$1" - - [ -f "bootstrap" ] && \ - x_ ./bootstrap $bootstrapargs - [ -f "autogen.sh" ] && \ - x_ ./autogen.sh $autogenargs - [ -f "configure" ] && \ - x_ ./configure $autoconfargs; : - - ) || err "can't bootstrap project: $1" "check_autoconf" "$@"; : -} - -check_makefile() -{ - [ ! -f "$1/Makefile" ] && [ ! -f "$1/makefile" ] && \ - [ ! -f "$1/GNUmakefile" ] && \ - return 1; : -} - -copy_elf() -{ - [ -f "$listfile" ] && \ - x_ mkdir -p "$dest_dir" - - if [ -f "$listfile" ]; then - while read -r f; do - [ -f "$srcdir/$f" ] && \ - x_ cp "$srcdir/$f" "$dest_dir"; : - - done < "$listfile" || err \ - "cannot read '$listfile'" "copy_elf" "$@"; : - fi - - ( x_ make clean -C "$srcdir" $cleanargs ) || \ - err "can't make-clean '$srcdir'" "copy_elf" "$@"; : -} diff --git a/include/vendor.sh b/include/vendor.sh deleted file mode 100644 index 10daeca3..00000000 --- a/include/vendor.sh +++ /dev/null @@ -1,624 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only - -# Copyright (c) 2022 Caleb La Grange -# Copyright (c) 2022 Ferass El Hafidi -# Copyright (c) 2023-2026 Leah Rowe - -# These are variables and functions, extending the functionality of -# inject.sh, to be used with lbmk; they are kept separate here, so that -# the main inject.sh can be as similar as possible between lbmk and cbmk, -# so that cherry-picking lbmk patches into cbmk yields fewer merge conflicts. - -# When reading this file, you should imagine that it is part of inject.sh, -# with inject.sh concatenated onto vendor.sh; they are inexorably intertwined. -# The main "mk" script sources vendor.sh first, and then inject.sh, in lbmk. - -e6400_unpack="$xbmkpwd/src/bios_extract/dell_inspiron_1100_unpacker.py" -me7updateparser="$xbmkpwd/util/me7_update_parser/me7_update_parser.py" -pfs_extract="$xbmkpwd/src/biosutilities/Dell_PFS_Extract.py" -uefiextract="$xbmkpwd/elf/uefitool/uefiextract" -bsdtar="$xbmkpwd/elf/libarchive/bsdtar" -bsdunzip="$xbmkpwd/elf/libarchive/bsdunzip" -vendir="vendorfiles" -appdir="$vendir/app" -vfix="DO_NOT_FLASH_YET._FIRST,_INJECT_FILES_VIA_INSTRUCTIONS_ON_LIBREBOOT.ORG_" - -# lbmk-specific extension to the "checkvars" variable (not suitable for cbmk) -checkvarschk="CONFIG_INCLUDE_SMSC_SCH5545_EC_FW CONFIG_HAVE_MRC \ - CONFIG_HAVE_ME_BIN CONFIG_LENOVO_TBFW_BIN CONFIG_VGA_BIOS_FILE \ - CONFIG_FSP_M_FILE CONFIG_FSP_S_FILE CONFIG_KBC1126_FW1 CONFIG_KBC1126_FW2" - -# lbmk-specific extensions to the "checkvars" variable (not suitable for cbmk) -checkvarsxbmk="CONFIG_ME_BIN_PATH CONFIG_SMSC_SCH5545_EC_FW_FILE \ - CONFIG_FSP_FULL_FD CONFIG_KBC1126_FW1_OFFSET CONFIG_KBC1126_FW2_OFFSET \ - CONFIG_FSP_USE_REPO CONFIG_VGA_BIOS_ID CONFIG_BOARD_DELL_E6400 \ - CONFIG_FSP_S_CBFS CONFIG_HAVE_REFCODE_BLOB CONFIG_REFCODE_BLOB_FILE \ - CONFIG_FSP_FD_PATH CONFIG_IFD_BIN_PATH CONFIG_MRC_FILE CONFIG_FSP_M_CBFS" - -# lbmk-specific extensions; general variables -eval "`newvar cbdir cbfstoolref has_hashes hashfile kbc1126_ec_dump mecleaner \ - mfs nuke rom vcfg xromsize _7ztest _dest _dl _dl_bin _me _metmp _pre_dest`" - -# lbmk-specific extensions; declared by pkg.cfg files in config/vendor/ -eval "`newvar DL_hash DL_url DL_url_bkup E6400_VGA_bin_hash E6400_VGA_DL_hash \ - E6400_VGA_DL_url E6400_VGA_DL_url_bkup E6400_VGA_offset E6400_VGA_romname \ - EC_FW1_hash EC_FW2_hash EC_hash EC_url EC_url_bkup FSPFD_hash \ - FSPM_bin_hash FSPS_bin_hash ME11bootguard ME11delta ME11pch ME11sku \ - ME11version ME_bin_hash MEcheck MEclean MEshrink MRC_bin_hash \ - MRC_refcode_cbtree MRC_refcode_gbe REF_bin_hash SCH5545EC_bin_hash \ - SCH5545EC_DL_hash SCH5545EC_DL_url SCH5545EC_DL_url_bkup TBFW_bin_hash \ - TBFW_hash TBFW_size TBFW_url TBFW_url_bkup XBMKmecleaner`" - -download() -{ - [ $# -lt 1 ] && \ - err "No argument given" "download" "$@" - - export PATH="$PATH:/sbin" - board="$1" - - check_target || return 0 - readkconfig download -} - -getfiles() -{ - [ -n "$CONFIG_HAVE_ME_BIN" ] && \ - fetch intel_me "$DL_url" "$DL_url_bkup" "$DL_hash" \ - "$CONFIG_ME_BIN_PATH" curl "$ME_bin_hash" - [ -n "$CONFIG_INCLUDE_SMSC_SCH5545_EC_FW" ] && \ - fetch sch5545ec "$SCH5545EC_DL_url" "$SCH5545EC_DL_url_bkup" \ - "$SCH5545EC_DL_hash" "$CONFIG_SMSC_SCH5545_EC_FW_FILE" \ - "curl" "$SCH5545EC_bin_hash" - [ -n "$CONFIG_KBC1126_FW1" ] && \ - fetch kbc1126ec "$EC_url" "$EC_url_bkup" "$EC_hash" \ - "$CONFIG_KBC1126_FW1" curl "$EC_FW1_hash" - [ -n "$CONFIG_KBC1126_FW2" ] && \ - fetch kbc1126ec "$EC_url" "$EC_url_bkup" "$EC_hash" \ - "$CONFIG_KBC1126_FW2" curl "$EC_FW2_hash" - [ -n "$CONFIG_VGA_BIOS_FILE" ] && \ - fetch e6400vga "$E6400_VGA_DL_url" "$E6400_VGA_DL_url_bkup" \ - "$E6400_VGA_DL_hash" "$CONFIG_VGA_BIOS_FILE" "curl" \ - "$E6400_VGA_bin_hash" - [ -n "$CONFIG_HAVE_MRC" ] && \ - fetch "mrc" "$MRC_url" "$MRC_url_bkup" "$MRC_hash" \ - "$CONFIG_MRC_FILE" "curl" "$MRC_bin_hash" - [ -n "$CONFIG_REFCODE_BLOB_FILE" ] && \ - fetch "refcode" "$MRC_url" "$MRC_url_bkup" "$MRC_hash" \ - "$CONFIG_REFCODE_BLOB_FILE" "curl" "$REF_bin_hash" - [ -n "$CONFIG_LENOVO_TBFW_BIN" ] && \ - fetch "tbfw" "$TBFW_url" "$TBFW_url_bkup" "$TBFW_hash" \ - "$CONFIG_LENOVO_TBFW_BIN" "curl" "$TBFW_bin_hash" - [ -n "$CONFIG_FSP_M_FILE" ] && \ - fetch "fsp" "$CONFIG_FSP_FD_PATH" "$CONFIG_FSP_FD_PATH" \ - "$FSPFD_hash" "$CONFIG_FSP_M_FILE" "copy" "$FSPM_bin_hash" - [ -n "$CONFIG_FSP_S_FILE" ] && \ - fetch "fsp" "$CONFIG_FSP_FD_PATH" "$CONFIG_FSP_FD_PATH" \ - "$FSPFD_hash" "$CONFIG_FSP_S_FILE" copy "$FSPS_bin_hash"; : -} - -fetch() -{ - dl_type="$1" - dl="$2" - dl_bkup="$3" - dlsum="$4" - _dest="${5##*../}" - _pre_dest="$XBMK_CACHE/tmpdl/check" - dlop="$6" - binsum="$7" - - [ -z "$binsum" ] && \ - err "binsum is empty (no checksum)" "fetch" "$@" - - _dl="$XBMK_CACHE/file/$dlsum" # internet file to extract from e.g. .exe - _dl_bin="$XBMK_CACHE/file/$binsum" # extracted file e.g. me.bin - - [ "$5" = "/dev/null" ] && \ - return 0 - - # an extracted vendor file will be placed in pre_dest first, for - # verifying its checksum. if it matches, it is later moved to _dest - remkdir "${_pre_dest%/*}" "$appdir" - - # HACK: if grabbing fsp from coreboot, fix the path for lbmk - if [ "$dl_type" = "fsp" ]; then - dl="${dl##*../}" - _cdp="$dl" - - [ ! -f "$_cdp" ] && \ - _cdp="$cbdir/$_cdp" - [ -f "$_cdp" ] && \ - dl="$_cdp" - - dl_bkup="${dl_bkup##*../}" - _cdp="$dl_bkup" - - [ ! -f "$_cdp" ] && \ - _cdp="$cbdir/$_cdp" - [ -f "$_cdp" ] && \ - dl_bkup="$_cdp"; : - fi - - # download the file (from the internet) to extract from: - - xbget "$dlop" "$dl" "$dl_bkup" "$_dl" "$dlsum" - x_ rm -Rf "${_dl}_extracted" - - # skip extraction if a cached extracted file exists: - - ( xbget copy "$_dl_bin" "$_dl_bin" "$_dest" "$binsum" 2>/dev/null ) || : - [ -f "$_dest" ] && \ - return 0 - - x_ mkdir -p "${_dest%/*}" - - if [ "$dl_type" != "fsp" ]; then - extract_archive "$_dl" "$appdir" || \ - [ "$dl_type" = "e6400vga" ] || \ - err "$_dest $dl_type: !extract" "fetch" "$@" - fi - - x_ extract_$dl_type "$_dl" "$appdir" - set -u -e - - # some functions don't output directly to the given file, _pre_dest. - # instead, they put multiple files there, but we need the one matching - # the given hashsum. So, search for a matching file via bruteforce: - ( fx_ "mkdst $binsum" x_ find "${_pre_dest%/*}" -type f ) || : - - bad_checksum "$binsum" "$_dest" || \ - [ ! -f "$_dest" ] || \ - return 0; : - - [ -z "$binsum" ] && \ - printf "'%s': checksum undefined\n" "$_dest" 1>&2 - - if [ -L "$_dest" ]; then - printf "WARNING: '%s' is a link!\n" "$_dest" 1>&2 - else - x_ rm -f "$_dest" - fi - - err "Can't safely extract '$_dest', for board '$board'" "fetch" "$@" -} - -mkdst() -{ - if bad_checksum "$1" "$2" 2>/dev/null; then - x_ rm -f "$2" - else - x_ mv "$2" "$_dl_bin" - x_ cp "$_dl_bin" "$_dest" - - exit 1 - fi -} - -extract_intel_me() -{ - if e "$mecleaner" f missing; then - err "$cbdir: me_cleaner missing" "extract_intel_me" "$@" - fi - - mfs="" - _7ztest="$xbtmp/metmp/a" - _metmp="$xbtmp/me.bin" - - x_ rm -f "$_metmp" "$xbtmp/a" - x_ rm -Rf "$_7ztest" - - # maintain compatibility with older configs - # because in the past, shrink was assumed - [ -z "$MEshrink" ] && \ - MEshrink="y" - [ "$MEshrink" != "y" ] && [ "$MEshrink" != "n" ] && \ - err "MEshrink set badly on '$board' vendor config" - - if [ "$ME11bootguard" = "y" ]; then - if [ -z "$ME11delta" ] || [ -z "$ME11version" ] || \ - [ -z "$ME11sku" ] || [ -z "$ME11pch" ]; then - err "$board: ME11delta/ME11version/ME11sku/ME11pch" \ - "extract_intel_me" "$@" - fi - - x_ ./mk -f deguard - fi - - set +u +e - - ( fx_ find_me x_ find "$xbmkpwd/$appdir" -type f ) || :; : - - set -u -e - - if [ "$ME11bootguard" != "y" ]; then - x_ mv "$_metmp" "$_pre_dest" - else - ( apply_deguard_hack ) || \ - err "deguard error on '$_dest'" "extract_intel_me" "$@"; : - fi -} - -# bruteforce Intel ME extraction. -# must be called inside a subshell. -find_me() -{ - [ -f "$_metmp" ] && \ - exit 1 # me.bin found - [ -L "$1" ] && \ - return 0 # symlinks disabled for security reasons - - _7ztest="${_7ztest}a" - - _r="-r" # re-locate modules - _trunc="-t" # -t: truncate the ME size - eval "`newvar _keep _pass`" # -k (keep fptr modules), -p (skip checks) - - [ "$ME11bootguard" = "y" ] && \ - mfs="--whitelist MFS" - if [ "$MEclean" = "n" ]; then - MEshrink="n" - _keep="-k" # keep ME modules, don't delete anything - mfs="" # no MFS whitelist needed, due to -r: - fi - if [ "$MEclean" = "n" ] || [ "$MEshrink" != "y" ]; then - eval "`newvar _r _trunc`" - fi - [ "$MEcheck" = "n" ] && \ - _pass="-p" # skip fptr check - [ -n "$mfs" ] && \ - _r="" # cannot re-locate modules if using --whitelist MFS - - if "$mecleaner" $mfs $_r $_keep $_pass $_trunc -O "$xbtmp/a" \ - -M "$_metmp" "$1" || [ -f "$_metmp" ]; then - : # me.bin extracted from a full image with ifd, then shrunk - elif "$mecleaner" $mfs $_r $_pass $_keep $_trunc -O "$_metmp" "$1" || \ - [ -f "$_metmp" ]; then - : # me.bin image already present, and we shrunk it - elif "$me7updateparser" $_keep -O "$_metmp" "$1"; then - : # thinkpad sandybridge me.bin image e.g. x220/t420 - elif extract_archive "$1" "$_7ztest"; then - : # scan newly extracted archive within extracted archive - else - return 0 # can't extract, so try the next file - fi - - [ -f "$_metmp" ] && \ - exit 1 # me.bin found - - ( fx_ find_me x_ find "$_7ztest" -type f ) || exit 1; : # 1==me found -} - -apply_deguard_hack() -{ - x_ cd src/deguard - - x_ ./finalimage.py --delta "data/delta/$ME11delta" \ - --version "$ME11version" --pch "$ME11pch" --sku "$ME11sku" \ - --fake-fpfs data/fpfs/zero --input "$_metmp" --output "$_pre_dest" -} - -extract_archive() -{ - innoextract "$1" -d "$2" || \ - python "$pfs_extract" "$1" -e || \ - 7z x "$1" -o"$2" || \ - "$bsdtar" -C "$2" -xf "$1" || \ - "$bsdunzip" "$1" -d "$2" || \ - return 1 - - [ -d "${_dl}_extracted" ] && \ - x_ cp -R "${_dl}_extracted" "$2"; : -} - -extract_kbc1126ec() -{ - ( extract_kbc1126ec_dump ) || \ - err "$board: can't extract kbc1126 fw" "extract_kbc1126ec" "$@" - - # throw error if either file is missing - x_ e "$appdir/ec.bin.fw1" f - x_ e "$appdir/ec.bin.fw2" f - - x_ cp "$appdir/"ec.bin.fw* "${_pre_dest%/*}/" -} - -extract_kbc1126ec_dump() -{ - x_ cd "$appdir/" - - mv Rompaq/68*.BIN ec.bin || \ - unar -D ROM.CAB Rom.bin || \ - unar -D Rom.CAB Rom.bin || \ - unar -D 68*.CAB Rom.bin || \ - err "!kbc1126 unar" "extract_kbc1126ec" "$@" - - [ ! -f "ec.bin" ] && \ - x_ mv Rom.bin ec.bin - - x_ e ec.bin f - x_ "$kbc1126_ec_dump" ec.bin -} - -extract_e6400vga() -{ - set +u +e - - if [ -z "$E6400_VGA_offset" ] || [ -z "$E6400_VGA_romname" ]; then - err "$board: E6400_VGA_romname/E6400_VGA_offset unset" \ - "extract_e6400vga" "$@" - fi - - tail -c +$E6400_VGA_offset "$_dl" | gunzip > "$appdir/bios.bin" || : - - ( - x_ cd "$appdir" - x_ e "bios.bin" f - "$e6400_unpack" bios.bin || printf "TODO: fix dell extract util\n" - ) || err "can't extract e6400 vga rom" "extract_e6400vga" "$@" - - x_ cp "$appdir/$E6400_VGA_romname" "$_pre_dest" - - set -u -e -} - -extract_sch5545ec() -{ - # full system ROM (UEFI), to extract with UEFIExtract: - _bios="${_dl}_extracted/Firmware/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! - - x_ "$uefiextract" "$_bios" - x_ cp "$_sch5545ec_fw" "$_pre_dest" -} - -# Lenovo ThunderBolt firmware updates: -# https://pcsupport.lenovo.com/us/en/products/laptops-and-netbooks/thinkpad-t-series-laptops/thinkpad-t480-type-20l5-20l6/20l5/solutions/ht508988 -extract_tbfw() -{ - [ -z "$TBFW_size" ] && \ - err "$board: TBFW_size unset" "extract_tbfw" "$@" - - fx_ copytb x_ find "$appdir" -type f -name "TBT.bin" -} - -copytb() -{ - if [ -f "$1" ] && [ ! -L "$1" ]; then - x_ dd if=/dev/null of="$1" bs=1 seek=$TBFW_size - x_ mv "$1" "$_pre_dest" - - return 1 - fi -} - -extract_fsp() -{ - x_ python "$cbdir/3rdparty/fsp/Tools/SplitFspBin.py" split -f "$1" \ - -o "${_pre_dest%/*}" -n "Fsp.fd" -} - -setvfile() -{ - [ -n "$vcfg" ] && for c in $checkvarschk - do - do_getvfile="n" - vcmd="[ \"\${$c}\" != \"/dev/null\" ] && [ -n \"\${$c}\" ]" - - eval "$vcmd && do_getvfile=\"y\"" - - [ "$do_getvfile" = "y" ] && \ - if getvfile "$@"; then - return 0 - fi; : - done && return 1; : -} - -getvfile() -{ - if e "config/vendor/$vcfg/pkg.cfg" f missing; then - return 1 - fi - - . "config/vendor/$vcfg/pkg.cfg" || \ - err "Can't read 'config/vendor/$vcfg/pkg.cfg'" "getvfile" "$@" - - bootstrap - - if [ $# -gt 0 ]; then - # download vendor files - - getfiles - else - # inject vendor files - - fx_ prep x_ find "$tmpromdir" -maxdepth 1 -type f -name "*.rom" - ( check_vendor_hashes ) || \ - err "$archive: Can't verify hashes" "getvfile" "$@"; : - fi - -} - -bootstrap() -{ - cbdir="src/coreboot/$tree" - kbc1126_ec_dump="$xbmkpwd/$cbdir/util/kbc1126/kbc1126_ec_dump" - cbfstool="elf/coreboot/$tree/cbfstool" - rmodtool="elf/coreboot/$tree/rmodtool" - - mecleaner="$xbmkpwd/$cbdir/util/me_cleaner/me_cleaner.py" - [ "$XBMKmecleaner" = "y" ] && \ - mecleaner="$xbmkpwd/src/me_cleaner/me_cleaner.py" - - x_ ./mk -f coreboot "${cbdir##*/}" - x_ ./mk -f me_cleaner - - x_ ./mk -b bios_extract - x_ ./mk -b biosutilities - x_ ./mk -b uefitool - x_ ./mk -b libarchive # for bsdtar and bsdunzip - - [ -d "${kbc1126_ec_dump%/*}" ] && \ - x_ make -C "$cbdir/util/kbc1126" - - if [ -n "$MRC_refcode_cbtree" ]; then - cbfstoolref="elf/coreboot/$MRC_refcode_cbtree/cbfstool" - x_ ./mk -d coreboot "$MRC_refcode_cbtree"; : - fi -} - -prep() -{ - _xrom="$1" - _xromname="${1##*/}" - _xromnew="${_xrom%/*}/${_xromname#"$vfix"}" - - [ "$nuke" = "nuke" ] && \ - _xromnew="${_xrom%/*}/$vfix${_xrom##*/}" - - if e "$_xrom" f missing; then - return 0 - fi - - [ -z "${_xromname#"$vfix"}" ] && \ - err "$_xromname / $vfix: name match" "prep" "$@" - - # Remove the prefix and 1-byte pad - if [ "${_xromname#"$vfix"}" != "$_xromname" ] \ - && [ "$nuke" != "nuke" ]; then - - unpad_one_byte "$_xrom" - x_ mv "$_xrom" "$_xromnew" - - _xrom="$_xromnew" - fi - - if [ "$nuke" = "nuke" ]; then - ( mksha512 "$_xrom" "vendorhashes" ) || err; : - fi - - add_vfiles "$_xrom" || \ - return 1 # no need to insert files - - if [ "$nuke" = "nuke" ]; then - pad_one_byte "$_xrom" - x_ mv "$_xrom" "$_xromnew" - fi -} - -mksha512() -{ - build_sbase - - [ "${1%/*}" != "$1" ] && \ - x_ cd "${1%/*}" - - x_ "$sha512sum" ./"${1##*/}" >> "$2" || \ - err "!sha512sum \"$1\" > \"$2\"" "mksha512" "$@" -} - -add_vfiles() -{ - rom="$1" - - if [ "$has_hashes" != "y" ] && [ "$nuke" != "nuke" ]; then - printf "'%s' has no hash file. Skipping.\n" "$archive" 1>&2 - return 1 - elif [ "$has_hashes" = "y" ] && [ "$nuke" = "nuke" ]; then - printf "'%s' has a hash file. Skipping nuke.\n" "$archive" 1>&2 - return 1 - fi - - [ -n "$CONFIG_HAVE_REFCODE_BLOB" ] && \ - vfile "fallback/refcode" "$CONFIG_REFCODE_BLOB_FILE" "stage" - [ "$CONFIG_HAVE_MRC" = "y" ] && \ - vfile "mrc.bin" "$CONFIG_MRC_FILE" "mrc" "0xfffa0000" - [ "$CONFIG_HAVE_ME_BIN" = "y" ] && \ - vfile IFD "$CONFIG_ME_BIN_PATH" me - [ -n "$CONFIG_KBC1126_FW1" ] && \ - vfile ecfw1.bin "$CONFIG_KBC1126_FW1" raw \ - "$CONFIG_KBC1126_FW1_OFFSET" - [ -n "$CONFIG_KBC1126_FW2" ] && \ - vfile ecfw2.bin "$CONFIG_KBC1126_FW2" raw \ - "$CONFIG_KBC1126_FW2_OFFSET" - [ -n "$CONFIG_VGA_BIOS_FILE" ] && [ -n "$CONFIG_VGA_BIOS_ID" ] && \ - vfile "pci$CONFIG_VGA_BIOS_ID.rom" "$CONFIG_VGA_BIOS_FILE" \ - optionrom - [ "$CONFIG_INCLUDE_SMSC_SCH5545_EC_FW" = "y" ] && \ - [ -n "$CONFIG_SMSC_SCH5545_EC_FW_FILE" ] && \ - vfile sch5545_ecfw.bin "$CONFIG_SMSC_SCH5545_EC_FW_FILE" raw - [ -z "$CONFIG_FSP_USE_REPO" ] && [ -z "$CONFIG_FSP_FULL_FD" ] && \ - [ -n "$CONFIG_FSP_M_FILE" ] && \ - vfile "$CONFIG_FSP_M_CBFS" "$CONFIG_FSP_M_FILE" fsp --xip - [ -z "$CONFIG_FSP_USE_REPO" ] && [ -z "$CONFIG_FSP_FULL_FD" ] && \ - [ -n "$CONFIG_FSP_S_FILE" ] && \ - vfile "$CONFIG_FSP_S_CBFS" "$CONFIG_FSP_S_FILE" fsp - - xchanged="y" - - printf "ROM image successfully patched: %s\n" "$rom" -} - -vfile() -{ - [ "$2" = "/dev/null" ] && \ - return 0 - - cbfsname="$1" - _dest="${2##*../}" - blobtype="$3" - - _offset="" - - if [ "$blobtype" = "fsp" ] && [ $# -gt 3 ]; then - _offset="$4" - elif [ $# -gt 3 ] && _offset="-b $4" && [ -z "$4" ]; then - err "$rom: offset given but empty (undefined)" "vfile" "$@" - fi - - [ "$nuke" != "nuke" ] && \ - x_ e "$_dest" f - - if [ "$cbfsname" = "IFD" ]; then - if [ "$nuke" = "nuke" ]; then - x_ "$ifdtool" $ifdprefix --nuke $blobtype "$rom" \ - -O "$rom" - else - x_ "$ifdtool" $ifdprefix -i $blobtype:$_dest "$rom" \ - -O "$rom" - fi - elif [ "$nuke" = "nuke" ]; then - x_ "$cbfstool" "$rom" remove -n "$cbfsname" - elif [ "$blobtype" = "stage" ]; then - # the only stage we handle is refcode - - x_ rm -f "$xbtmp/refcode" - x_ "$rmodtool" -i "$_dest" -o "$xbtmp/refcode" - x_ "$cbfstool" "$rom" add-stage -f "$xbtmp/refcode" \ - -n "$cbfsname" -t stage - else - x_ "$cbfstool" "$rom" add -f "$_dest" -n "$cbfsname" \ - -t $blobtype $_offset - fi - - xchanged="y" -} - -# must be called from a subshell -check_vendor_hashes() -{ - build_sbase - - x_ cd "$tmpromdir" - - if [ "$has_hashes" != "n" ] && [ "$nuke" != "nuke" ]; then - ( x_ "$sha512sum" -c "$hashfile" ) || \ - x_ sha1sum -c "$hashfile" - fi - - x_ rm -f "$hashfile" -} -- cgit v1.2.1