diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/get.sh | 365 | ||||
| -rw-r--r-- | include/git.sh | 154 | ||||
| -rw-r--r-- | include/init.sh | 480 | ||||
| -rw-r--r-- | include/inject.sh | 234 | ||||
| -rw-r--r-- | include/lib.sh | 405 | ||||
| -rw-r--r-- | include/mrc.sh | 86 | ||||
| -rw-r--r-- | include/release.sh | 130 | ||||
| -rw-r--r-- | include/rom.sh | 547 | ||||
| -rw-r--r-- | include/tree.sh | 772 | ||||
| -rw-r--r-- | include/vendor.sh | 1127 | 
10 files changed, 3220 insertions, 1080 deletions
diff --git a/include/get.sh b/include/get.sh new file mode 100644 index 00000000..9ab6956d --- /dev/null +++ b/include/get.sh @@ -0,0 +1,365 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +# Copyright (c) 2020-2021,2023-2025 Leah Rowe <leah@libreboot.org> +# Copyright (c) 2022 Caleb La Grange <thonkpeasant@protonmail.com> + +url="" +bkup_url="" + +depend="" +loc="" +subcurl="" +subcurl_bkup="" +subgit="" +subgit_bkup="" +subhash="" + +tmpgit="$xbtmp/gitclone" +tmpgitcache="$xbtmp/tmpgit" + +fetch_targets() +{ +	if [ ! -d "src/$project/$tree" ]; then +		git_prep "$url" "$bkup_url" \ +		    "$xbmkpwd/$configdir/$tree/patches" \ +		    "src/$project/$tree" "submod" +	fi +} + +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 + +	if [ -n "$xgcctree" ]; then +		x_ ./mk -f coreboot "$xgcctree" +	fi +	if [ -n "$depend" ]; then +		for d in $depend ; do +			x_ ./mk -f $d +		done +	fi + +	clone_project +} + +clone_project() +{ +	if singletree "$project"; then +		loc="src/$project" + +		if [ -d "$loc" ]; then +			return 0 +		fi + +		remkdir "${tmpgit%/*}" +		git_prep "$url" "$bkup_url" \ +		    "$xbmkpwd/config/$project/patches" "$loc" +	fi +} + +git_prep() +{ +	printf "Creating code directory, src/%s/%s\n" "$project" "$tree" + +	_patchdir="$3" +	_loc="$4" # $1 and $2 are gitrepo and gitrepo_backup + +	if [ -z "$rev" ]; then +		err "$project/$tree: rev not set" "git_prep" "$@" +	fi + +	xbget git "$1" "$2" "$tmpgit" "$rev" "$_patchdir" +	if singletree "$project" || [ $# -gt 4 ]; then +		dx_ fetch_submodule "$mdir/module.list" +	fi + +	if [ "$_loc" != "${_loc%/*}" ]; then +		x_ xbmkdir "${_loc%/*}" +	fi + +	x_ mv "$tmpgit" "$_loc" +} + +fetch_submodule() +{ +	mcfgdir="$mdir/${1##*/}" + +	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" "$@" + +	if [ -n "$subgit" ] || [ -n "$subgit_bkup" ]; then +		st="$st git" +	fi +	if [ -n "$subcurl" ] || [ -n "$subcurl_bkup" ]; then +		st="$st curl" +	fi + +	st="${st# }" +	if [ "$st" = "git curl" ]; then +		err "$mdir: git+curl defined" "fetch_submodule" "$@" +	fi + +	if [ -z "$st" ]; then +		return 0 +	fi + +	if [ "$st" = "curl" ]; then +		if [ -z "$subcurl" ] || [ -z "$subcurl_bkup" ]; then +			err "subcurl/subcurl_bkup not both set" \ +			    "fetch_submodule" "$@" +		fi +	elif [ -z "$subgit" ] || [ -z "$subgit_bkup" ]; then +		err "subgit/subgit_bkup not both set" "fetch_submodule" "$@" +	elif [ -z "$subhash" ]; then +		err "subhash not set" "fetch_submodule" "$@" +	fi + +	if [ "$st" = "git" ]; then +		x_ rm -Rf "$tmpgit/$1" +		xbget "$st" "$subgit" "$subgit_bkup" "$tmpgit/$1" \ +		    "$subhash" "$mdir/${1##*/}/patches" +	else +		xbget "$st" "$subcurl" "$subcurl_bkup" "$tmpgit/$1" \ +		    "$subhash" "$mdir/${1##*/}/patches" +	fi +} + +# 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() +{ +	if [ "$1" != "curl" ] && [ "$1" != "copy" ] && [ "$1" != "git" ]; then +		err "Bad dlop (arg 1)" "xbget" "$@" +	fi + +	for url in "$2" "$3" +	do +		if [ -z "$url" ]; then +			err "empty URL given in" "xbget" "$@" +		elif ! try_fetch "$url" "$@"; then +			continue +		fi + +		case "$1" in +		git) +			if [ ! -d "$4" ]; then +				continue +			fi +			;; +		*) +			if [ ! -f "$4" ]; then +				continue +			fi +			;; +		esac +		return 0 # successful download/copy +	done + +	err "failed to download file/repository" "xbget" "$@"; : +} + +try_fetch() +{ +	if [ "$2" = "git" ]; then +		if ! try_fetch_git "$@"; then +			return 1 +		fi +	else +		if ! try_fetch_file "$@"; then +			return 1 +		fi +	fi +} + +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 + +	if [ "$XBMK_CACHE_MIRROR" = "y" ]; then +		cached="mirror" +	else +		cached="clone" +	fi +	cached="$cached/${1#*://}" +	cached="$XBMK_CACHE/$cached" + +	x_ xbmkdir "${5%/*}" "${cached%/*}" + +	if ! try_$2 "$cached" "$@"; then +		return 1 +	elif [ ! -d "$cached" ]; then +		return 1 +	fi + +	if [ ! -d "$5" ]; then +		tmpclone "$cached" "$5" "$6" "$7" || \ +		    err "Can't clone final repo" "try_fetch" "$@"; : +	fi + +	if [ ! -d "$5" ]; then +		return 1 +	fi +} + +try_fetch_file() +{ +	cached="file/$6" +	cached="$XBMK_CACHE/$cached" + +	x_ xbmkdir "${5%/*}" "${cached%/*}" + +	if bad_checksum "$6" "$cached" 2>/dev/null; then +		x_ rm -f "$cached" +	fi + +	if [ ! -f "$cached" ]; then +		if ! try_$2 "$cached" "$@"; then +			return 1 +		fi +	fi + +	if [ -f "$5" ]; then +		if bad_checksum "$6" "$5" 2>/dev/null; then +			x_ cp "$cached" "$5" +		fi +	fi + +	if [ ! -f "$cached" ]; then +		return 1 +	elif bad_checksum "$6" "$cached"; then +		x_ rm -f "$cached" + +		return 1 +	fi + +	if [ "$cached" != "$5" ]; then +		x_ cp "$cached" "$5" +	fi + +	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_ xbmkdir "${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 "$@" + +	if [ "$csum" = "$1" ]; then +		return 1 +	else +		x_ rm -f "$2" +		printf "BAD SHA512 %s, '%s'; need %s\n" "$csum" "$2" "$1" 1>&2 +	fi +} + +tmpclone() +{ +	( x_ git clone "$1" "$2" ) || return 1 +	( x_ git -C "$2" reset --hard "$3" ) || return 1 + +	if [ ! -d "$4" ]; then +		return 0 +	fi + +	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 --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/git.sh b/include/git.sh deleted file mode 100644 index fb0b2b42..00000000 --- a/include/git.sh +++ /dev/null @@ -1,154 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-or-later -# Copyright (c) 2020-2021,2023-2024 Leah Rowe <leah@libreboot.org> -# Copyright (c) 2022 Caleb La Grange <thonkpeasant@protonmail.com> - -eval "`setvars "" loc url bkup_url subfile subhash subrepo subrepo_bkup \ -    depend subfile_bkup repofail`" - -fetch_targets() -{ -	[ -n "$tree_depend" ] && [ "$tree_depend" != "$tree" ] && \ -		x_ ./mk -f "$project" "$tree_depend" -	e "src/$project/$tree" d && return 0 - -	printf "Creating %s tree %s\n" "$project" "$tree" -	git_prep "$loc" "$loc" "$PWD/$configdir/$tree/patches" \ -	    "src/$project/$tree" u; nuke "$project/$tree" "$project/$tree" -} - -fetch_project() -{ -	eval "`setvars "" xtree tree_depend`" -	eval "`setcfg "config/git/$project/pkg.cfg"`" - -	chkvars url - -	[ -n "$xtree" ] && x_ ./mk -f coreboot "$xtree" -	[ -z "$depend" ] || for d in $depend ; do -		printf "'%s' needs '%s'; grabbing '%s'\n" "$project" "$d" "$d" -		x_ ./mk -f $d -	done -	clone_project - -	for x in config/git/*; do -		[ -d "$x" ] && nuke "${x##*/}" "src/${x##*/}" 2>/dev/null -	done; return 0 -} - -clone_project() -{ -	loc="$XBMK_CACHE/repo/$project" && singletree "$project" && \ -	    loc="src/$project" -	printf "Downloading project '%s' to '%s'\n" "$project" "$loc" - -	e "$loc" d missing && remkdir "${tmpgit%/*}" && git_prep \ -	    "$url" "$bkup_url" "$PWD/config/$project/patches" "$loc"; : -} - -git_prep() -{ -	_patchdir="$3"; _loc="$4" # $1 and $2 are gitrepo and gitrepo_backup - -	chkvars rev; tmpclone "$1" "$2" "$tmpgit" "$rev" "$_patchdir" -	if singletree "$project" || [ $# -gt 4 ]; then -		prep_submodules "$_loc"; fi - -	[ "$project" = "coreboot" ] && [ -n "$xtree" ] && [ $# -gt 2 ] && \ -	    [ "$xtree" != "$tree" ] && link_crossgcc "$_loc" -	[ "$XBMK_RELEASE" = "y" ] && \ -	    [ "$_loc" != "$XBMK_CACHE/repo/$project" ] && rmgit "$tmpgit" - -	move_repo "$_loc" -} - -prep_submodules() -{ -	[ -f "$mdir/module.list" ] && while read -r msrcdir; do -		fetch_submodule "$msrcdir" -	done < "$mdir/module.list"; return 0 -} - -fetch_submodule() -{ -	mcfgdir="$mdir/${1##*/}" -	eval "`setvars "" subhash subrepo subrepo_bkup subfile subfile_bkup \ -	    st`" -	[ ! -f "$mcfgdir/module.cfg" ] || . "$mcfgdir/module.cfg" || \ -	    $err "! . $mcfgdir/module.cfg" - -	for xt in repo file; do -		_seval="if [ -n \"\$sub$xt\" ] || [ -n \"\$sub${xt}_bkup\" ]" -		eval "$_seval; then st=\"\$st \$xt\"; fi" -	done -	st="${st# }" && [ "$st" = "repo file" ] && $err "$mdir: repo+file" - -	[ -z "$st" ] && return 0 # subrepo/subfile not defined -	chkvars "sub${st}" "sub${st}_bkup" "subhash" - -	[ "$st" = "file" ] && download "$subfile" "$subfile_bkup" \ -	    "$tmpgit/$1" "$subhash" && return 0 -	rm -Rf "$tmpgit/$1" || $err "!rm '$mdir' '$1'" -	tmpclone "$subrepo" "$subrepo_bkup" "$tmpgit/$1" "$subhash" \ -	    "$mdir/${1##*/}/patches" -} - -tmpclone() -{ -	livepull="n" && [ "$repofail" = "y" ] && \ -	    printf "Cached clone failed; trying online.\n" 1>&2 && livepull="y" - -	repofail="n" - -	[ $# -lt 6 ] || rm -Rf "$3" || $err "git retry: !rm $3 ($1)" -	repodir="$XBMK_CACHE/repo/${1##*/}" && [ $# -gt 5 ] && repodir="$3" -	mkdir -p "$XBMK_CACHE/repo" || $err "!rmdir $XBMK_CACHE/repo" - -	if [ "$livepull" = "y" ] && [ ! -d "$repodir" ]; then -		git clone "$1" "$repodir" || git clone $2 "$repodir" || \ -		    $err "!clone $1 $2 $repodir $4 $5" # -	elif [ -d "$repodir" ] && [ $# -lt 6 ]; then -		git -C "$repodir" pull || sleep 3 || git -C "$repodir" pull \ -		    || sleep 3 || git -C "$repodir" pull || : -	fi -	( -	[ $# -gt 5 ] || git clone "$repodir" "$3" || $err "!clone $repodir $3" -	git -C "$3" reset --hard "$4" || $err "!reset $1 $2 $3 $4 $5" -	git_am_patches "$3" "$5" -	) || repofail="y" - -	[ "$repofail" = "y" ] && [ $# -lt 6 ] && tmpclone "$@" retry -	[ "$repofail" = "y" ] && $err "!clone $1 $2 $3 $4 $5"; : -} - -git_am_patches() -{ -	for p in "$2/"*; do -		[ -L "$p" ] && continue; [ -e "$p" ] || continue -		[ -d "$p" ] && git_am_patches "$1" "$p" && continue -		[ ! -f "$p" ] || git -C "$1" am "$p" || $err "$1 $2: !am $p" -	done; return 0 -} - -link_crossgcc() -{ -	( -	x_ cd "$tmpgit/util" && x_ rm -Rf crossgcc -	ln -s "../../$xtree/util/crossgcc" crossgcc || $err "$1: !xgcc link" -	) || $err "$1: !xgcc link" -} - -move_repo() -{ -	[ "$1" = "${1%/*}" ] || x_ mkdir -p "${1%/*}" -	mv "$tmpgit" "$1" || $err "git_prep: !mv $tmpgit $1" -} - -# can delete from multi- and single-tree projects. -# called from script/trees when downloading sources. -nuke() -{ -	e "config/${1%/}/nuke.list" f missing || while read -r nukefile; do -		rmf="src/${2%/}/$nukefile" && [ -L "$rmf" ] && continue -		e "$rmf" e missing || rm -Rf "$rmf" || $err "!rm $rmf, ${2%/}" -	done < "config/${1%/}/nuke.list"; return 0 -} diff --git a/include/init.sh b/include/init.sh new file mode 100644 index 00000000..abd06862 --- /dev/null +++ b/include/init.sh @@ -0,0 +1,480 @@ +# SPDX-License-Identifier: GPL-3.0-only + +# Copyright (c) 2022 Caleb La Grange <thonkpeasant@protonmail.com> +# Copyright (c) 2022 Ferass El Hafidi <vitali64pmemail@protonmail.com> +# Copyright (c) 2020-2025 Leah Rowe <leah@libreboot.org> +# Copyright (c) 2025 Alper Nebi Yasak <alpernebiyasak@gmail.com> + +export LC_COLLATE=C +export LC_ALL=C + +projectname="libreboot" +projectsite="https://libreboot.org/" + +if [ -z "${PATH+x}" ]; then +	export PATH="/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games" +fi + +sha512sum="util/sbase/sha512sum" + +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" "$@" + +	if [ "$(id -u)" = "0" ]; then +		err "this command as root is not permitted" "xbmk_init" "$@" +	fi + +	export PWD="$xbmkpwd" +	x_ xbmkdir "$basetmp" + +	if [ ! -e "cache" ]; then +		x_ xbmkdir "cache" +	fi + +	for init_cmd in get_version set_env set_threads git_init child_exec; do +		if ! xbmk_$init_cmd "$@"; then +			break +		fi +	done +} + +xbmkpkg() +{ +	xchk xbmkpkg "$@" + +	if [ $# -gt 2 ]; then +		reinstall="$3" +	fi + +	. "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 + +	x_ $pkg_add $pkglist + +	if [ -n "$aur_notice" ]; then +		printf "You need AUR packages: %s\n" "$aur_notice" 1>&2 +	fi +} + +xbmk_get_version() +{ +	if [ -f ".version" ]; then +		read -r version < ".version" || \ +		    err "can't read version file" "xbmk_get_version" "$@" +	fi +	if [ -f ".versiondate" ]; then +		read -r versiondate < ".versiondate" || \ +		    err "can't read versiondate" xbmk_get_version "$@" +	fi + +	if [ -f ".version" ] && [ -z "$version" ]; then +		err "version not set" "xbmk_get_version" "$@" +	fi +	if [ -f ".versiondate" ] && [ -z "$versiondate" ]; then +		err "versiondate not set" "xbmk_get_version" "$@" +	fi + +	if [ ! -e ".git" ] && [ ! -f ".version" ]; then +		version="unknown" +	fi +	if [ ! -e ".git" ] && [ ! -f ".versiondate" ]; then +		versiondate="1716415872" +	fi + +	xbmk_sanitize_version + +	if [ -n "$version" ]; then +		relname="$projectname-$version" +	fi +} + +# 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 +	if [ -n "${TMPDIR+x}" ] && [ "${TMPDIR%_*}" != "$basetmp/xbmk" ]; then +		unset TMPDIR +	fi +	if [ -n "${TMPDIR+x}" ]; then +		export TMPDIR="$TMPDIR" +		xbtmp="$TMPDIR" +	fi +	if [ -n "${TMPDIR+x}" ]; then +		is_child="y" +	fi + +	if [ "$is_child" = "y" ] +	then +		# child instance of xbmk, so we stop init after this point +		# and execute the given user command upon return: + +		xbmk_child_set_env + +		return 1 +	else +		# parent instance of xbmk, so we continue initialising. +		# a parent instance of xbmk never processes its own +		# command directly; instead, it calls a child instance +		# of xbmk, and exits with the corresponding return status. +		 +		xbmk_parent_set_env + +		return 0 +	fi +} + +xbmk_child_set_env() +{ +	xbmk_child_set_tmp + +	if [ -z "${XBMK_CACHE+x}" ]; then +		err "XBMK_CACHE unset on child" "xbmk_set_env" "$@" +	fi +	if [ -z "${XBMK_THREADS+x}" ]; then +		xbmk_set_threads; : +	fi +	if [ -z "${XBMK_CACHE_MIRROR+x}" ]; then +		xbmk_set_mirror +	fi +} + +xbmk_child_set_tmp() +{ +	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 +		if [ "$xtmpdir" = "$xbtmp" ]; then +			err "pre-existing '$xbtmp'" "xbmk_parent_check_tmp" "$@" +		fi +	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" + +	if [ -e "$XBMK_CACHE" ] && [ ! -d "$XBMK_CACHE" ]; then +		err "cachedir '$XBMK_CACHE' is a file" \ +		    "xbmk_parent_set_export" "$@" +	fi + +	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) + +	if [ -z "${XBMK_RELEASE+x}" ]; then +		export XBMK_RELEASE="n" +	fi +	if [ "$XBMK_RELEASE" = "Y" ]; then +		export XBMK_RELEASE="y" +	fi +	if [ "$XBMK_RELEASE" != "y" ]; then +		export XBMK_RELEASE="n" +	fi +} + +xbmk_set_threads() +{ +	if [ -z "${XBMK_THREADS+x}" ]; then +		export XBMK_THREADS=1 +	fi +	if ! expr "X$XBMK_THREADS" : "X-\{0,1\}[0123456789][0123456789]*$" \ +	    1>/dev/null 2>/dev/null; then +		export XBMK_THREADS=1 +	fi +} + +xbmk_set_version() +{ +	version_="$version" +	if [ -e ".git" ]; then +		version="$(git describe --tags HEAD 2>&1)" || \ +		    version="git-$(git rev-parse HEAD 2>&1)" || \ +		    version="$version_" +	fi + +	versiondate_="$versiondate" +	if [ -e ".git" ]; then +		versiondate="$(git show --no-patch --no-notes \ +		    --pretty='%ct' HEAD)" || versiondate="$versiondate_" +	fi + +	if [ -z "$version" ] || [ -z "$versiondate" ]; then +		err "version and/or versiondate unset" "xbmk_set_version" "$@" +	fi + +	update_xbmkver "." + +	relname="$projectname-$version" +	export LOCALVERSION="-$projectname-${version%%-*}" +} + +xbmk_set_pyver() +{ +	python="python3" +	pyver="2" +	pyv="import sys; print(sys.version_info[:])" + +	if ! pybin python3 1>/dev/null; then +		python="python" +	fi +	if [ "$python" = "python3" ]; then +		pyver="3" +	fi +	if ! pybin "$python" 1>/dev/null; then +		pyver="" +	fi +	if [ -n "$pyver" ]; then +		"`x_ pybin "$python"`" -c "$pyv" 1>/dev/null \ +		    2>/dev/null || \ +		    err "Can't detect Python version." "xbmk_set_pyver" "$@" +	fi +	if [ -n "$pyver" ]; then +		pyver="$("$(pybin "$python")" -c "$pyv" | awk '{print $1}')" +		pyver="${pyver#(}" +		pyver="${pyver%,}" +	fi +	if [ "${pyver%%.*}" != "3" ]; then +		err "Bad python version (must by 3.x)" "xbmk_set_pyver" "$@" +	fi + +	# 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 +	if ! command -v "$1" 1>/dev/null 2>/dev/null; then +		venv=0 +	fi +	if [ $venv -gt 0 ]; then +		if ! "$1" -c "$py" 1>/dev/null 2>/dev/null; then +			venv=0 +		fi +	fi + +	# ideally, don't rely on PATH or hardcoded paths if python venv. +	# use the *real*, direct executable linked to by the venv symlink: + +	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 +	if ! command -v "$1" 2>/dev/null; then +		return 1 +	fi +} + +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 + +	if [ -z "${XBMK_CACHE_MIRROR+x}" ]; then +		export XBMK_CACHE_MIRROR="n" +	fi +	if [ "$XBMK_CACHE_MIRROR" != "y" ]; then +		export XBMK_CACHE_MIRROR="n" +	fi +} + +xbmk_git_init() +{ +	for gitarg in "--global user.name" "--global user.email"; do +		gitcmd="git config $gitarg" +		if ! $gitcmd 1>/dev/null 2>/dev/null; then +			err "Run this first: $gitcmd \"your ${gitcmd##*.}\"" \ +			    "xbmk_git_init" "$@" +		fi +	done + +	if [ -L ".git" ]; then +		err "'$xbmkpwd/.git' is a symlink" "xbmk_git_init" "$@" +	fi +	if [ -e ".git" ]; then +		return 0 +	fi + +	# GNU-specific extensions of date are used. +	# TODO: that is a bug. fix it! + +	x_ date --version | grep "GNU coreutils" 1>/dev/null 2>/dev/null || \ +	    err "Non-GNU date implementation" "xbmk_git_init" "$@" + +	cdate="`x_ date -Rud @$versiondate || err "can't get date"`" || \ +	    err "can't get date" "xbmk_git_init" "$@" + +	x_ git init 1>/dev/null 2>/dev/null +	x_ git add -A . 1>/dev/null 2>/dev/null +	x_ git commit -m "$projectname $version" --date "$cdate" \ +	    --author="xbmk <xbmk@example.com>" 1>/dev/null 2>/dev/null +	x_ git tag -a "$version" -m "$projectname $version" 1>/dev/null \ +	    2>/dev/null; : +} + +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 new file mode 100644 index 00000000..ee3df6af --- /dev/null +++ b/include/inject.sh @@ -0,0 +1,234 @@ +# SPDX-License-Identifier: GPL-3.0-only + +# Copyright (c) 2022 Caleb La Grange <thonkpeasant@protonmail.com> +# Copyright (c) 2022 Ferass El Hafidi <vitali64pmemail@protonmail.com> +# Copyright (c) 2023-2025 Leah Rowe <leah@libreboot.org> + +cbcfgsdir="config/coreboot" +tmpromdel="$XBMK_CACHE/DO_NOT_FLASH" +nvm="util/nvmutil/nvm" +ifdtool="elf/coreboot/default/ifdtool" + +checkvars="CONFIG_GBE_BIN_PATH" +if [ -n "$checkvarsxbmk" ]; then +	checkvars="$checkvars $checkvarsxbmk" +fi +if [ -n "$checkvarschk" ]; then +	checkvars="$checkvars $checkvarschk" +fi + +archive="" +board="" +boarddir="" +IFD_platform="" +ifdprefix="" +new_mac="" +tmpromdir="" +tree="" +xchanged="" + +eval "`setvars "" $checkvars`" + +inject() +{ +	remkdir "$tmpromdel" + +	if [ $# -lt 1 ]; then +		err "No options specified" "inject" "$@" +	fi + +	archive="$1"; +	new_mac="xx:xx:xx:xx:xx:xx" + +	new_mac="" +	nuke="" +	xchanged="" + +	[ $# -gt 1 ] && case "$2" in +	nuke) +		new_mac="" +		nuke="nuke" +		;; +	setmac) +		if [ $# -gt 2 ]; then +			new_mac="$3" && \ +			if [ -z "$new_mac" ]; then +				err "Empty MAC address specified" "inject" "$@" +			fi +		fi +		;; +	*) +		err "Unrecognised inject mode: '$2'" "inject" "$@" ;; +	esac + +	if [ "$new_mac" = "keep" ]; then +		new_mac="" +	fi + +	check_release +	if check_target; then +		if ! patch_release; then +			return 0 +		fi +	fi +	if [ "$xchanged" = "y" ]; then +		remktar +	fi + +	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() +{ +	if [ -L "$archive" ]; then +		err "'$archive' is a symlink" "check_release" "$@" +	fi +	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" "$@" + +	if [ -z "$archivename" ]; then +		err "Can't determine archive name" "check_release" "$@" +	fi + +	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() +{ +	if [ "$board" != "${board#serprog_}" ]; then +		return 1 +	fi + +	boarddir="$cbcfgsdir/$board" + +	. "$boarddir/target.cfg" || \ +	    err "Can't read '$boarddir/target.cfg'" "check_target" "$@" + +	if [ -z "$tree" ]; then +		err "tree unset in '$boarddir/target.cfg'" "check_target" "$@" +	fi + +	x_ ./mk -d coreboot "$tree" + +	ifdtool="elf/coreboot/$tree/ifdtool" + +	if [ -n "$IFD_platform" ]; then +		ifdprefix="-p $IFD_platform" +	fi +} + +patch_release() +{ +	if [ "$nuke" != "nuke" ]; then +		x_ ./mk download "$board" +	fi + +	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 + +	if ! readkconfig; then +		return 1 +	elif [ -n "$new_mac" ] && [ -n "$CONFIG_GBE_BIN_PATH" ]; then +		modify_mac +	fi +} + +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" "$@" + +	if ! setvfile "$@"; then +		return 1 +	fi +} + +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_ "$nvm" "$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_ "$nvm" "$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/lib.sh b/include/lib.sh index 2b630797..feb411e0 100644 --- a/include/lib.sh +++ b/include/lib.sh @@ -1,274 +1,267 @@  # SPDX-License-Identifier: GPL-3.0-only +  # Copyright (c) 2022 Caleb La Grange <thonkpeasant@protonmail.com>  # Copyright (c) 2022 Ferass El Hafidi <vitali64pmemail@protonmail.com>  # Copyright (c) 2020-2025 Leah Rowe <leah@libreboot.org> +# Copyright (c) 2025 Alper Nebi Yasak <alpernebiyasak@gmail.com> -export LC_COLLATE=C -export LC_ALL=C - -_ua="Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0" - -ifdtool="elf/ifdtool/default/ifdtool" -cbfstool="elf/cbfstool/default/cbfstool" -rmodtool="elf/cbfstool/default/rmodtool" -tmpgit="$PWD/tmp/gitclone" -grubdata="config/data/grub" -err="err_" - -pyver="2" -python="python3" -command -v python3 1>/dev/null || python="python" -command -v $python 1>/dev/null || pyver="" -[ -n "$pyver" ] && pyver="$($python --version | awk '{print $2}')" -if [ "${pyver%%.*}" != "3" ]; then -	printf "Wrong python version, or python missing. Must be v 3.x.\n" 1>&2 -	exit 1 -fi +cbfstool="elf/coreboot/default/cbfstool" +rmodtool="elf/coreboot/default/rmodtool" -err_() +mkrom_tarball()  { -	printf "ERROR %s: %s\n" "$0" "$1" 1>&2; exit 1 +	update_xbmkver "$1" +	mktarball "$1" "${1%/*}/${relname}_${1##*/}.tar.xz" + +	x_ rm -Rf "$1"  } -setvars() +update_xbmkver()  { -	_setvars="" && [ $# -lt 2 ] && $err "setvars: too few arguments" -	val="$1" && shift 1 && for var in "$@"; do -		_setvars="$var=\"$val\"; $_setvars" -	done; printf "%s\n" "${_setvars% }" +	xbmk_sanitize_version + +	printf "%s\n" "$version" > "$1/.version" || \ +	    err "can't write '$1'" "update_xbmkver" "$@"; : + +	printf "%s\n" "$versiondate" > "$1/.versiondate" || \ +	    err "can't write '$versiondate'" "update_xbmkver" "$@"; :  } -chkvars() + +xbmk_sanitize_version()  { -	for var in "$@"; do -		eval "[ -n "\${$var+x}" ] || \$err \"$var unset\"" -		eval "[ -n \"\$$var\" ] || \$err \"$var unset\"" -	done; return 0 -} +	if [ -z "$version" ]; then +		return 0 +	fi -eval "`setvars "" _nogit board reinstall versiondate projectsite projectname \ -    aur_notice configdir datadir version relname xbmk_parent`" +	version="`printf "%s\n" "$version" | sed -e 's/\t//g'`" +	version="`printf "%s\n" "$version" | sed -e 's/\ //g'`" +	version="`printf "%s\n" "$version" | sed -e 's/\.\.//g'`" +	version="`printf "%s\n" "$version" | sed -e 's/\.\///g'`" +	version="`printf "%s\n" "$version" | sed -e 's/\//-/g'`" -for fv in projectname projectsite version versiondate; do -	eval "[ ! -f \"$fv\" ] || read -r $fv < \"$fv\" || :" -done; chkvars projectname projectsite +	version="${version#-}" -setcfg() +	if [ -z "$version" ]; then +		err "'version' empty after sanitization" \ +		    "xbmk_sanitize_version" "$@" +	fi +} + +mktarball()  { -	[ $# -gt 1 ] && printf "e \"%s\" f missing && return %s;\n" "$1" "$2" -	[ $# -gt 1 ] || \ -		printf "e \"%s\" f not && %s \"Missing config\";\n" "$1" "$err" -	printf ". \"%s\" || %s \"Could not read config\";\n" "$1" "$err" +	printf "Creating tar archive '%s' from directory '%s'\n" "$2" "$1" + +	if [ "${2%/*}" != "$2" ]; then +		x_ xbmkdir "${2%/*}" +	fi + +	x_ tar -c "$1" | xz -T$XBMK_THREADS -9e > "$2" || \ +	    err "can't make tarball '$1'" "mktarball" "$@"  }  e()  { -	es_t="e" && [ $# -gt 1 ] && es_t="$2" +	es_t="e" + +	if [ $# -gt 1 ]; then +		es_t="$2" +	fi +  	es2="already exists"  	estr="[ -$es_t \"\$1\" ] || return 1" -	[ $# -gt 2 ] && estr="[ -$es_t \"\$1\" ] && return 1" && es2="missing" -	eval "$estr"; printf "%s %s\n" "$1" "$es2" 1>&2 +	if [ $# -gt 2 ]; then +		estr="[ -$es_t \"\$1\" ] && return 1" +		es2="missing" +	fi + +	eval "$estr" + +	printf "%s %s\n" "$1" "$es2" 1>&2  } -install_packages() +setvars()  { -	[ $# -lt 2 ] && $err "fewer than two arguments" -	[ $# -gt 2 ] && reinstall="$3" +	_setvars="" + +	if [ $# -lt 2 ]; then -	eval "`setcfg "config/dependencies/$2"`" +		return 0 +	else +		val="$1" -	chkvars pkg_add pkglist -	$pkg_add $pkglist || $err "Cannot install packages" +		shift 1 -	[ -n "$aur_notice" ] && \ -	    printf "You need AUR packages: %s\n" "$aur_notice" 1>&2; : +		while [ $# -gt 0 ]; do +			printf "%s=\"%s\"\n" "$1" "$val" + +			shift 1 +		done +	fi  } -if [ $# -gt 0 ] && [ "$1" = "dependencies" ]; then -	install_packages "$@" || exit 1 -	exit 0 -fi - -id -u 1>/dev/null 2>/dev/null || $err "suid check failed (id -u)" -[ "$(id -u)" != "0" ] || $err "this command as root is not permitted" - -# XBMK_CACHE is a directory, for caching downloads and git repositories -[ -z "${XBMK_CACHE+x}" ] && export XBMK_CACHE="$PWD/cache" -[ -z "$XBMK_CACHE" ] && export XBMK_CACHE="$PWD/cache" -[ -L "$XBMK_CACHE" ] && [ "$XBMK_CACHE" = "$PWD/cache" ] && \ -    $err "cachedir is default, $PWD/cache, but it exists and is a symlink" -[ -L "$XBMK_CACHE" ] && export XBMK_CACHE="$PWD/cache" -[ -f "$XBMK_CACHE" ] && $err "cachedir '$XBMK_CACHE' exists but it's a file" - -# unify all temporary files/directories in a single TMPDIR -[ -z "${TMPDIR+x}" ] || [ "${TMPDIR%_*}" = "/tmp/xbmk" ] || unset TMPDIR -[ -n "${TMPDIR+x}" ] && export TMPDIR="$TMPDIR" -if [ -z "${TMPDIR+x}" ]; then -	[ -f "lock" ] && $err "$PWD/lock exists. Is a build running?" -	export TMPDIR="/tmp" -	export TMPDIR="$(mktemp -d -t xbmk_XXXXXXXX)" -	touch lock || $err "cannot create 'lock' file" -	rm -Rf "$XBMK_CACHE/xbmkpath" || $err "cannot remove xbmkpath" -	mkdir -p "$XBMK_CACHE/xbmkpath" || $err "cannot create xbmkpath" -	export PATH="$XBMK_CACHE/xbmkpath:$PATH" || \ -	    $err "Can't create xbmkpath" -	xbmk_parent="y" -fi - -# 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="n" - -[ -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 # user gave a non-integer - -x_() { -	[ $# -lt 1 ] || "$@" || \ -	    $err "Unhandled non-zero exit: $(echo "$@")"; return 0 + +# return 0 if project is single-tree, otherwise 1 +# e.g. coreboot is multi-tree, so 1 +singletree() +{ +	( fx_ "eval exit 1 && err" find "config/$1/"*/ -type f \ +	    -name "target.cfg" ) || return 1; :  } -[ -e ".git" ] || [ -f "version" ] || printf "unknown\n" > version || \ -    $err "Cannot generate unknown version file" -[ -e ".git" ] || [ -f "versiondate" ] || printf "1716415872\n" > versiondate \ -    || $err "Cannot generate unknown versiondate file" - -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_" -for p in projectname version versiondate projectsite; do -	chkvars "$p"; eval "x_ printf \"%s\\n\" \"\$$p\" > $p" -done -relname="$projectname-$version" -export LOCALVERSION="-$projectname-${version%%-*}" - -check_defconfig() +findpath()  { -	[ -d "$1" ] || $err "Target '$1' not defined." -	for x in "$1"/config/*; do -		[ -f "$x" ] && printf "%s\n" "$x" && return 1 -	done; return 0 +	if [ $# -lt 1 ]; then +		err "findpath: No arguments provided" "findpath" "$@" +	fi + +	while [ $# -gt 0 ] +	do +		found="`readlink -f "$1" 2>/dev/null`" || return 1; : + +		if [ -z "$found" ]; then +			found="`realpath "$1" 2>/dev/null`" || \ +			    return 1 +		fi + +		printf "%s\n" "$found" + +		shift 1 +	done  } -remkdir() +pad_one_byte()  { -	rm -Rf "$1" || $err "remkdir: !rm -Rf \"$1\"" -	mkdir -p "$1" || $err "remkdir: !mkdir -p \"$1\"" +	paddedfile="`mktemp || err "mktemp pad_one_byte"`" || \ +	    err "can't make tmp file" "pad_one_byte" "$@" + +	x_ cat "$1" config/data/coreboot/0 > "$paddedfile" || \ +	    err "could not pad file '$paddedfile'" "pad_one_byte" "$1"; : + +	x_ mv "$paddedfile" "$1"  } -mkrom_tarball() +unpad_one_byte()  { -	printf "%s\n" "$version" > "$1/version" || $err "$1 !version" -	printf "%s\n" "$versiondate" > "$1/versiondate" || $err "$1 !vdate" -	printf "%s\n" "$projectname" > "$1/projectname" || $err "$1 !pname" +	xromsize="$(expr $(stat -c '%s' "$1") - 1)" || \ +	    err "can't increment file size" "unpad_one_byte" "$@" + +	if [ $xromsize -lt 524288 ]; then +		err "too small, $xromsize: $1" "unpad_one_byte" "$@" +	fi + +	unpaddedfile="`mktemp || err "mktemp unpad_one_byte"`" || \ +	    err "can't make tmp file" "unpad_one_byte" "$@" -	mktarball "$1" "${1%/*}/${relname}_${1##*/}.tar.xz"; x_ rm -Rf "$1"; : +	x_ dd if="$1" of="$unpaddedfile" bs=$xromsize count=1 +	x_ mv "$unpaddedfile" "$1"  } -mktarball() +build_sbase()  { -	if [ "${2%/*}" != "$2" ]; then -		mkdir -p "${2%/*}" || $err "mk, !mkdir -p \"${2%/*}\"" +	if [ ! -f "$sha512sum" ]; then +		x_ make -C "$xbmkpwd/util/sbase"  	fi -	tar -c "$1" | xz -T$XBMK_THREADS -9e > "$2" || $err "mktarball 2, $1"  } -mksha512sum() +remkdir()  { -	( -	[ "${1%/*}" != "$1" ] && x_ cd "${1%/*}" -	sha512sum ./"${1##*/}" >> "$2" || $err "!sha512sum \"$1\" > \"$2\"" -	) || $err "failed to create tarball checksum" +	x_ rm -Rf "$@" +	x_ xbmkdir "$@"  } -rmgit() +xbmkdir()  { -	( -	cd "$1" || $err "!cd gitrepo $1" -	find . -name ".git" -exec rm -Rf {} + || $err "!rm .git $1" -	find . -name ".gitmodules" -exec rm -Rf {} + || $err "!rm .gitmod $1" -	) || $err "Cannot remove .git/.gitmodules in $1" +	while [ $# -gt 0 ] +	do +		if [ ! -d "$1" ]; then +			x_ mkdir -p "$1" +		fi + +		shift 1 +	done  } -# return 0 if project is single-tree, otherwise 1 -# e.g. coreboot is multi-tree, so 1 -singletree() +fx_() +{ +	xchk fx_ "$@" +	xcmd="$1" + +	xfile="`mktemp || err "can't create tmpfile"`" || \ +	    err "can't make tmpfile" "fx_" "$@" + +	x_ rm -f "$xfile" +	x_ touch "$xfile" + +	shift 1 + +	"$@" 2>/dev/null | sort 1>"$xfile" 2>/dev/null || \ +	    err "can't sort to '$xfile'" "fx_" "$xcmd" "$@" + +	dx_ "$xcmd" "$xfile" || : +	x_ rm -f "$xfile" +} + +dx_()  { -	for targetfile in "config/${1}/"*/target.cfg; do -		[ -e "$targetfile" ] && [ -f "$targetfile" ] && return 1; : -	done; return 0 +	xchk dx_ "$@" + +	if [ ! -f "$2" ]; then +		return 0 +	fi + +	while read -r fx; do +		$1 "$fx" || return 1; : +	done < "$2" || err "cannot read '$2'" "dx_" "$@"; :  } -# can grab from the internet, or copy locally. -# if copying locally, it can only copy a file. -download() +x_()  { -	_dlop="curl" && [ $# -gt 4 ] && _dlop="$5" -	cached="$XBMK_CACHE/file/$4" -	dl_fail="n" # 1 url, 2 url backup, 3 destination, 4 checksum -	vendor_checksum "$4" "$cached" 2>/dev/null && dl_fail="y" -	[ "$dl_fail" = "n" ] && e "$3" f && return 0 -	mkdir -p "${3%/*}" "$XBMK_CACHE/file" || \ -	    $err "!mkdir '$3' '$XBMK_CACHE/file'" -	for url in "$1" "$2"; do -		[ "$dl_fail" = "n" ] && break -		[ -z "$url" ] && continue -		rm -f "$cached" || $err "!rm -f '$cached'" -		if [ "$_dlop" = "curl" ]; then -			curl --location --retry 3 -A "$_ua" "$url" \ -			    -o "$cached" || wget --tries 3 -U "$_ua" "$url" \ -			    -O "$cached" || continue -		elif [ "$_dlop" = "copy" ]; then -			[ -L "$url" ] && \ -				printf "dl %s %s %s %s: '%s' is a symlink\n" \ -				    "$1" "$2" "$3" "$4" "$url" 1>&2 && continue -			[ ! -f "$url" ] && \ -				printf "dl %s %s %s %s: '%s' not a file\n" \ -				    "$1" "$2" "$3" "$4" "$url" 1>&2 && continue -			cp "$url" "$cached" || continue -		else -			$err "$1 $2 $3 $4: Unsupported dlop type: '$_dlop'" -		fi -		vendor_checksum "$4" "$cached" || dl_fail="n" -	done; [ "$dl_fail" = "y" ] && $err "$1 $2 $3 $4: not downloaded" -	[ "$cached" = "$3" ] || cp "$cached" "$3" || $err "!d cp $cached $3"; : +	if [ $# -lt 1 ]; then +		return 0 +	elif [ -z "$1" ]; then +		err "Empty first arg" "x_" "$@" +	else +		"$@" || err "Unhandled error" "x_" "$@" +	fi  } -vendor_checksum() +xchk()  { -	[ "$(sha512sum "$2" | awk '{print $1}')" != "$1" ] || return 1 -	printf "Bad checksum for file: %s\n" "$2" 1>&2; rm -f "$2" || :; : +	if [ $# -lt 3 ]; then +		err "$1 needs at least two arguments" "xchk" "$@" +	elif [ -z "$2" ] || [ -z "$3" ]; then +		err "arguments must not be empty" "xchk" "$@" +	fi  } -cbfs() +err()  { -	fRom="$1" # image to operate on -	fAdd="$2" # file to add -	fName="$3" # filename when added in CBFS - -	ccmd="add-payload" && [ $# -gt 3 ] && [ $# -lt 5 ] && ccmd="add" -	lzma="-c lzma" && [ $# -gt 3 ] && [ $# -lt 5 ] && lzma="-t $4" - -	# hack. TODO: do it better. this whole function is cursed -	if [ $# -gt 4 ]; then -		# add flat binary for U-Boot (u-boot.bin) on x86 -		if [ "$5" = "0x1110000" ]; then -			ccmd="add-flat-binary" -			lzma="-c lzma -l 0x1110000 -e 0x1110000" -		fi +	if [ $# -eq 1 ]; then +		printf "ERROR %s: %s\n" "$0" "$1" 1>&2 || : +	elif [ $# -gt 1 ]; then +		printf "ERROR %s: %s: in command with args: " "$0" "$1" 1>&2 +		shift 1 +		xprintf "$@" 1>&2 +	else +		printf "ERROR, but no arguments provided to err\n" 1>&2  	fi -	"$cbfstool" "$fRom" $ccmd -f "$fAdd" -n "$fName" $lzma || \ -	    $err "CBFS fail: $fRom $ccmd -f '$fAdd' -n '$fName' $lzma"; : +	exit 1  } -mk() +xprintf()  { -	mk_flag="$1" || $err "No argument given" -	shift 1 && for mk_arg in "$@"; do -		./mk $mk_flag $mk_arg || $err "./mk $mk_flag $mk_arg"; : -	done; : +	xprintfargs=0 +	while [ $# -gt 0 ]; do +		printf "\"%s\"" "$1" +		if [ $# -gt 1 ]; then +			printf " " +		fi + +		xprintfargs=1 +		shift 1 +	done +	if [ $xprintfargs -gt 0 ]; then +		printf "\n" +	fi  } diff --git a/include/mrc.sh b/include/mrc.sh index f5db2ff0..9c50af5c 100644 --- a/include/mrc.sh +++ b/include/mrc.sh @@ -1,61 +1,77 @@  # 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 and 2024 Leah Rowe. +# Modifications in this version are Copyright 2021,2023-2025 Leah Rowe.  # Original copyright detailed in repo: https://review.coreboot.org/coreboot/ -eval "`setvars "" MRC_url MRC_url_bkup MRC_hash MRC_board SHELLBALL`" +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: + +	if [ -z "$cbfstoolref" ]; then +		err "cbfstoolref not set" "extract_refcode" "$@" +	fi + +	x_ xbmkdir "${_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 +	if [ -n "$MRC_refcode_gbe" ]; then +		x_ dd if="config/ifd/hp820g2/1.bin" of="$appdir/ref" bs=1 \ +		    seek=$MRC_refcode_gbe count=1 conv=notrunc; : +	fi + +	x_ mv "$appdir/ref" "$_pre_dest" +}  extract_mrc()  { -	chkvars "MRC_board" "CONFIG_MRC_FILE" +	if [ -z "$MRC_board" ]; then +		err "MRC_board unset" "extract_mrc" "$@" +	elif [ -z "$CONFIG_MRC_FILE" ]; then +		err "CONFIG_MRC_FILE unset" "extract_mrc" "$@" +	fi +  	SHELLBALL="chromeos-firmwareupdate-$MRC_board"  	( -	x_ cd "$appdir" -	extract_partition "${MRC_url##*/}" -	extract_archive "$SHELLBALL" . -	) || $err "mrc download/extract failure" +		x_ cd "$appdir" +		extract_partition "${MRC_url##*/}" +		extract_archive "$SHELLBALL" . -	"$cbfstool" "$appdir/"bios.bin extract -n mrc.bin \ -	    -f "$_dest" -r RO_SECTION || $err "extract_mrc: !$cbfstool $_dest" +	) || err "mrc download/extract failure" "extract_mrc" "$@" -	[ -n "$CONFIG_REFCODE_BLOB_FILE" ] && extract_refcode; return 0 +	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" ) )) - -	dd if="${1%.zip}" of="root-a.ext2" bs=1024 skip=$(( $START / 1024 )) \ -	    count=$(( $SIZE / 1024 )) || $err "ex dd ${1%.zip}, root-a.ext2" - -	printf "cd /usr/sbin\ndump chromeos-firmwareupdate $SHELLBALL\nquit" \ -	    | debugfs "root-a.ext2" || $err "can't extract shellball" -} -extract_refcode() -{ -	_refdest="${CONFIG_REFCODE_BLOB_FILE##*../}" -	e "$_refdest" f && return 0 - -	# cbfstool changed the attributes scheme for stage files, -	# incompatible with older versions before coreboot 4.14, -	# so we need coreboot 4.13 cbfstool for certain refcode files -	chkvars cbfstoolref -	mkdir -p "${_refdest%/*}" || $err "ref: !mkdir -p ${_refdest%/*}" +	SIZE=$(( $( echo $ROOTP | cut -f4 -d\ | tr -d "B" ) )) -	"$cbfstoolref" "$appdir/bios.bin" extract \ -	    -m x86 -n fallback/refcode -f "$_refdest" -r RO_SECTION \ -	    || $err "extract_refcode $board: !cbfstoolref $_refdest" +	x_ dd if="${1%.zip}" of="root-a.ext2" bs=1024 \ +	    skip=$(( $START / 1024 )) count=$(( $SIZE / 1024 )) -	# enable the Intel GbE device, if told by offset MRC_refcode_gbe -	[ -z "$MRC_refcode_gbe" ] || dd if="config/ifd/hp820g2/1.bin" \ -	    of="$_refdest" bs=1 seek=$MRC_refcode_gbe count=1 conv=notrunc || \ -	    $err "extract_refcode $_refdest: byte $MRC_refcode_gbe"; return 0 +	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 new file mode 100644 index 00000000..e9017a05 --- /dev/null +++ b/include/release.sh @@ -0,0 +1,130 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +# Copyright (c) 2023-2025 Leah Rowe <leah@libreboot.org> + +reldest="" +reldir="" +relmode="" +rsrc="" +vdir="" + +release() +{ +	export XBMK_RELEASE="y" + +	reldir="release" + +	while getopts m: option +	do +		if [ -z "$OPTARG" ]; then +			err "empty argument not allowed" "release" "$@" +		fi + +		case "$option" in +		m) +			relmode="$OPTARG" +			;; +		*) +			err "invalid option '-$option'" "release" "$@" +			;; +		esac +	done + +	reldest="$reldir/$version" +	if [ -e "$reldest" ]; then +		err "already exists: \"$reldest\"" "release" "$@" +	fi + +	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 +	if [ "$relmode" != "src" ]; then +		prep_release bin +	fi +	x_ rm -Rf "$rsrc" + +	x_ xbmkdir "$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" +			if [ ! -e "cache" ]; then +				x_ ln -s "$XBMK_CACHE" "cache" +			fi +		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 index 2a7bc837..6f0e3529 100644 --- a/include/rom.sh +++ b/include/rom.sh @@ -1,193 +1,374 @@  # SPDX-License-Identifier: GPL-3.0-or-later +  # Copyright (c) 2014-2016,2020-2021,2023-2025 Leah Rowe <leah@libreboot.org>  # Copyright (c) 2021-2022 Ferass El Hafidi <vitali64pmemail@protonmail.com>  # Copyright (c) 2022 Caleb La Grange <thonkpeasant@protonmail.com>  # Copyright (c) 2022-2023 Alper Nebi Yasak <alpernebiyasak@gmail.com>  # Copyright (c) 2023-2024 Riku Viitanen <riku.viitanen@protonmail.com> -mkserprog() +grubdata="config/data/grub" + +buildser()  { -	[ "$_f" = "-d" ] && return 0 # dry run -	basename -as .h "$serdir/"*.h > "$TMPDIR/ser" || $err "!mk $1 $TMPDIR" - -	while read -r sertarget; do -		[ "$1" = "pico" ] && -		    x_ rm -rf "$sersrc/build" \ -		    && (pt=$(x_ grep "pico_cmake_set" \ -		          "$picosdk/src/boards/include/boards/$sertarget.h" \ -		        | grep "PICO_PLATFORM" | cut -d= -f2 | tr -d [:blank:]) -		        mkdir -p "$sersrc/build_$pt" -			ln -srf "$sersrc/build_$pt/" "$sersrc/build") \ -		    && x_ cmake -DPICO_BOARD="$sertarget" \ -		    -DPICO_SDK_PATH="$picosdk" -B "$sersrc/build" "$sersrc" \ -		    && x_ cmake --build "$sersrc/build" -		[ "$1" = "stm32" ] && x_ make -C "$sersrc" \ -		    libopencm3-just-make BOARD=$sertarget && x_ make -C \ -		    "$sersrc" BOARD=$sertarget; x_ mkdir -p "bin/serprog_$1" -		x_ mv "$serx" "bin/serprog_$1/serprog_$sertarget.${serx##*.}" -	done < "$TMPDIR/ser" - -	[ "$XBMK_RELEASE" = "y" ] && mkrom_tarball "bin/serprog_$1"; return 0 +	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_ xbmkdir "bin/serprog_$1" +	x_ mv "$serx" "bin/serprog_$1/serprog_$2.${serx##*.}"  }  copyps1bios()  { -	x_ rm -Rf bin/playstation -	x_ mkdir -p bin/playstation +	$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-2024 PCSX-Redux authors\n\n" \ -	    > bin/playstation/COPYING.txt || $err "!pcsx-redux copyright" -	cat config/snippet/mit >>bin/playstation/COPYING.txt || $err "!pcsx MIT" +	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 "`setvars "" grub_modules grub_install_modules`" -	$dry eval "`setcfg "$grubdata/module/$tree"`" -	$dry x_ rm -f "$srcdir/grub.elf"; $dry \ -	"$srcdir/grub-mkstandalone" --grub-mkimage="$srcdir/grub-mkimage" \ +	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" || \ -	    $err "$tree: cannot build grub.elf"; return 0 +	    "/boot/grub/grub.cfg=$grubdata/memdisk.cfg"; :  } -mkvendorfiles() +corebootpremake()  { -	[ -z "$mode" ] && $dry cook_coreboot_config -	check_coreboot_utils "$tree" +	if [ "$XBMK_RELEASE" = "y" ] && [ "$release" = "n" ]; then +		return 0 +	fi + +	$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" -	[ -z "$mode" ] && [ "$target" != "$tree" ] && \ -	    x_ ./mk download "$target"; return 0 +	    err "!mk $srcdir .coreboot-version" "corebootpremake" "$@" + +	if [ -z "$mode" ] && [ "$target" != "$tree" ]; then +		x_ ./mk download "$target" +	fi  }  cook_coreboot_config()  { -	[ -f "$srcdir/.config" ] || return 0 -	printf "CONFIG_CCACHE=y\n" >> "$srcdir/.config" || \ -	    $err "$srcdir/.config: Could not enable ccache" -	make -C "$srcdir" oldconfig || $err "Could not cook $srcdir/.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_utils() +check_coreboot_util()  { -	for util in cbfstool ifdtool; do -		[ "$badhash" = "y" ] && x_ rm -f "elf/$util/$1/$util" -		e "elf/$util/$1/$util" f && continue - -		utilelfdir="elf/$util/$1" -		utilsrcdir="src/coreboot/$1/util/$util" - -		utilmode="" && [ -n "$mode" ] && utilmode="clean" -		x_ make -C "$utilsrcdir" $utilmode -j$XBMK_THREADS $makeargs -		if [ -z "$mode" ] && [ ! -f "$utilelfdir/$util" ]; then -			x_ mkdir -p "$utilelfdir" -			x_ cp "$utilsrcdir/$util" "$utilelfdir" -			[ "$util" = "cbfstool" ] || continue -			x_ cp "$utilsrcdir/rmodtool" "$utilelfdir" -		elif [ -n "$mode" ]; then -			x_ rm -Rf "$utilelfdir" -		fi; continue -	done; return 0 +	if [ "$badhash" = "y" ]; then +		x_ rm -f "elf/coreboot/$tree/$1" +	fi +	if e "elf/coreboot/$tree/$1" f; then +		return 0 +	fi + +	utilelfdir="elf/coreboot/$tree" +	utilsrcdir="src/coreboot/$tree/util/$1" + +	utilmode="" +	if [ -n "$mode" ]; then +		utilmode="clean" +	fi + +	x_ make -C "$utilsrcdir" $utilmode -j$XBMK_THREADS $makeargs + +	if [ -n "$mode" ]; then +		# TODO: is this rm command needed? + +		x_ rm -Rf "$utilelfdir" + +		return 0 +	elif [ -n "$mode" ] || [ -f "$utilelfdir/$1" ]; then +		return 0 +	fi + +	x_ xbmkdir "$utilelfdir" +	x_ cp "$utilsrcdir/$1" "$utilelfdir" + +	if [ "$1" = "cbfstool" ]; then +		x_ cp "$utilsrcdir/rmodtool" "$utilelfdir" +	fi +} + +coreboot_pad_one_byte() +{ +	if [ "$XBMK_RELEASE" = "y" ] && [ "$release" = "n" ]; then +		return 0 +	fi + +	$if_not_dry_build \ +		pad_one_byte "$srcdir/build/coreboot.rom"  }  mkcorebootbin()  { -	[ "$target" = "$tree" ] && return 0 +	if [ "$XBMK_RELEASE" = "y" ] && [ "$release" = "n" ]; then +		return 0 +	fi + +	$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() +{ +	if [ "$target" = "$tree" ]; then +		return 0 +	fi -	tmprom="$TMPDIR/coreboot.rom" -	$dry x_ cp "$srcdir/build/coreboot.rom" "$tmprom" +	tmprom="$xbtmp/coreboot.rom" -	initmode="${defconfig##*/}"; displaymode="${initmode##*_}" -	[ "$displaymode" = "$initmode" ] && displaymode="" # "normal" config +	initmode="${defconfig##*/}" +	displaymode="${initmode##*_}" +	if [ "$displaymode" = "$initmode" ]; then +		# blank it for "normal" or "fspgop" configs: + +		displaymode="" +	fi  	initmode="${initmode%%_*}" -	cbfstool="elf/cbfstool/$tree/cbfstool" +	cbfstool="elf/coreboot/$tree/cbfstool" -	[ "$payload_uboot_i386" = "y" ] && \ -	    [ "$payload_uboot_amd64" = "y" ] && \ -		$err "'$target' enables 32- and 64-bit x86 U-Boot" +	# cbfstool option backends, if they exist +	cbfscfg="config/coreboot/$target/cbfs.cfg" -	if [ "$payload_uboot_i386" = "y" ] || \ -	    [ "$payload_uboot_amd64" = "y" ]; then -		printf "'%s' has x86 U-Boot; assuming SeaBIOS=y\n" \ -		    "$target" 1>&2 +	elfrom="elf/coreboot/$tree/$target/$initmode" +	if [ -n "$displaymode" ]; then +		elfrom="${elfrom}_$displaymode" +	fi +	elfrom="$elfrom/coreboot.rom" + +	$if_not_dry_build \ +		x_ cp "$elfrom" "$tmprom" + +	$if_not_dry_build \ +		unpad_one_byte "$tmprom" + +	if [ -n "$payload_uboot" ] && [ "$payload_uboot" != "amd64" ] && \ +	    [ "$payload_uboot" != "i386" ] && [ "$payload_uboot" != "arm64" ] +	then +		err "'$target' defines bad u-boot type '$payload_uboot'" \ +		    "mkcorebootbin_real" "$@" +	fi + +	if [ -n "$payload_uboot" ] && [ "$payload_uboot" != "arm64" ]; then  		payload_seabios="y"  	fi -	[ -n "$uboot_config" ] || uboot_config="default" -	[ "$payload_uboot" = "y" ] || payload_seabios="y" -	[ "$payload_grub" = "y" ] && payload_seabios="y" -	[ "$payload_seabios" = "y" ] && [ "$payload_uboot" = "y" ] && \ -	    $dry $err "$target: U-Boot(arm64) and SeaBIOS/GRUB both enabled." +	if [ -z "$uboot_config" ]; then +		uboot_config="default" +	fi +	if [ "$payload_grub" = "y" ]; then +		payload_seabios="y" +	fi +	if [ "$payload_seabios" = "y" ] && [ "$payload_uboot" = "arm64" ]; then +		$if_not_dry_build \ +			err "$target: U-Boot arm / SeaBIOS/GRUB both enabled" \ +			    "mkcorebootbin_real" "$@" +	fi -	[ -z "$grub_scan_disk" ] && grub_scan_disk="nvme ahci ata" +	if [ -z "$grub_scan_disk" ]; then +		grub_scan_disk="nvme ahci ata" +	fi +	if [ -z "$grubtree" ]; then +		grubtree="default" +	fi +	grubelf="elf/grub/$grubtree/$grubtree/payload/grub.elf" -	[ -n "$grubtree" ] || grubtree="default" -	grubelf="elf/grub/$grubtree/payload/grub.elf" +	if [ "$payload_memtest" != "y" ]; then +		payload_memtest="n" +	fi +	if [ "$(uname -m)" != "x86_64" ]; then +		payload_memtest="n" +	fi -	[ "$payload_memtest" = "y" ] || payload_memtest="n" -	[ "$(uname -m)" = "x86_64" ] || payload_memtest="n" +	if [ "$payload_grubsea" = "y" ] && [ "$initmode" = "normal" ]; then +		payload_grubsea="n" +	fi +	if [ "$payload_grub" != "y" ]; then +		payload_grubsea="n" +	fi -	[ "$payload_grubsea" = "y" ] && [ "$initmode" = "normal" ] && \ -	    payload_grubsea="n" -	[ "$payload_grub" = "y" ] || payload_grubsea="n" +	$if_dry_build \ +		return 0 -	if $dry grep "CONFIG_PAYLOAD_NONE=y" "$defconfig"; then -		[ "$payload_seabios" = "y" ] && pname="seabios" && \ -		    $dry add_seabios -		[ "$payload_uboot" = "y" ] && pname="uboot" && $dry add_uboot +	if [ -f "$cbfscfg" ]; then +		dx_ add_cbfs_option "$cbfscfg" +	fi + +	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" && $dry cprom; : +		pname="custom" +		cprom  	fi; :  } +# options for cbfs backend (as opposed to nvram/smmstore): + +add_cbfs_option() +{ +	# TODO: input sanitization (currently mitigated by careful config) + +	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()  { -	if [ "$payload_uboot_i386" = "y" ] || \ -	    [ "$payload_uboot_amd64" = "y" ]; then -		$dry add_uboot +	if [ -n "$payload_uboot" ] && [ "$payload_uboot" != "arm64" ]; then +		# we must add u-boot first, because it's added as a flat +		# binary at a specific offset for secondary program loader + +		$if_not_dry_build \ +			add_uboot  	fi -	_seabioself="elf/seabios/default/$initmode/bios.bin.elf" +	_seabioself="elf/seabios/default/default/$initmode/bios.bin.elf" +	[ "$initmode" = "fspgop" ] && \ +	    _seabioself="elf/seabios/default/default/libgfxinit/bios.bin.elf" + +	_seaname="fallback/payload" +	if [ "$payload_grubsea" = "y" ]; then +		 _seaname="seabios.elf" +	fi -	_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 -	_z="2"; [ "$initmode" = "vgarom" ] && _z="0" -	x_ "$cbfstool" "$tmprom" add-int -i $_z -n etc/pci-optionrom-exec +	opexec="2" +	if [ "$initmode" = "vgarom" ]; then +		opexec="0" +	fi +	x_ "$cbfstool" "$tmprom" add-int -i $opexec -n etc/pci-optionrom-exec +  	x_ "$cbfstool" "$tmprom" add-int -i 0 -n etc/optionroms-checksum -	[ "$initmode" = "libgfxinit" ] && \ -	    cbfs "$tmprom" "$seavgabiosrom" vgaroms/seavgabios.bin raw +	if [ "$initmode" = "libgfxinit" ] || [ "$initmode" = "fspgop" ]; then +		cbfs "$tmprom" "$seavgabiosrom" vgaroms/seavgabios.bin raw +	fi + +	if [ "$payload_memtest" = "y" ]; then +		# because why not have memtest? + +		cbfs "$tmprom" "elf/memtest86plus/memtest.bin" img/memtest +	fi + +	if [ "$payload_grub" = "y" ]; then +		add_grub +	fi + +	if [ "$payload_grubsea" != "y" ]; then +		# ROM image where SeaBIOS doesn't load grub/u-boot first. +		# U-Boot/GRUB available in ESC menu if enabled for the board -	[ "$payload_memtest" = "y" ] && cbfs "$tmprom" \ -	    "elf/memtest86plus/memtest.bin" img/memtest +		cprom +	fi + +	# now make "SeaUBoot" and "SeaGRUB" images, where SeaBIOS auto-loads +	# SeaBIOS or U-Boot first; users can bypass this by pressing ESC +	# in the SeaBIOS menu, to boot devices using SeaBIOS itself instead -	[ "$payload_grub" = "y" ] && add_grub +	if [ "$payload_uboot" = "amd64" ] && \ +	    [ "$displaymode" != "txtmode" ] && \ +	    [ "$initmode" != "normal" ] && [ "$payload_grubsea" != "y" ]; then +		pname="seauboot" +		cprom "seauboot" +	fi -	[ "$payload_grubsea" != "y" ] && cprom -	[ "$payload_uboot_amd64" = "y" ] && [ "$displaymode" != "txtmode" ] && \ -	    [ "$initmode" != "normal" ] && [ "$payload_grubsea" != "y" ] && \ -	    pname="seauboot" && cprom "seauboot" -	[ "$payload_grub" = "y" ] && pname="seagrub" && mkseagrub; : +	if [ "$payload_grub" = "y" ]; then +		pname="seagrub" +		mkseagrub +	fi  }  add_grub()  { -	_grubname="img/grub2" && [ "$payload_grubsea" = "y" ] && \ -	    _grubname="fallback/payload" +	# path in CBFS for the GRUB payload +	_grubname="img/grub2" +	if [ "$payload_grubsea" = "y" ]; then +		_grubname="fallback/payload" +	fi +  	cbfs "$tmprom" "$grubelf" "$_grubname" +  	printf "set grub_scan_disk=\"%s\"\n" "$grub_scan_disk" \ -	    > "$TMPDIR/tmpcfg" || $err "$target: !insert scandisk" -	cbfs "$tmprom" "$TMPDIR/tmpcfg" scan.cfg raw -	[ "$initmode" != "normal" ] && [ "$displaymode" != "txtmode" ] && \ -	    cbfs "$tmprom" "$grubdata/background/background1280x800.png" \ -	    "background.png" raw; : +	    > "$xbtmp/tmpcfg" || \ +	    err "$target: !insert scandisk" "add_grub" "$@" + +	cbfs "$tmprom" "$xbtmp/tmpcfg" scan.cfg raw + +	if [ "$initmode" != "normal" ] && [ "$displaymode" != "txtmode" ]; then +		cbfs "$tmprom" "$grubdata/background/background1280x800.png" \ +		    "background.png" raw +	fi  }  mkseagrub() @@ -197,20 +378,20 @@ mkseagrub()  	else  		cbfs "$tmprom" "$grubdata/bootorder" bootorder raw  	fi -	for keymap in config/data/grub/keymap/*.gkb; do -		[ -f "$keymap" ] && cprom "${keymap##*/}"; : -	done; : + +	fx_ cprom x_ find "$grubdata/keymap" -type f -name "*.gkb"  }  add_uboot()  {  	if [ "$displaymode" = "txtmode" ]; then -		printf "cb/%s: Cannot use U-Boot in text mode\n" \ -		    "$target" 1>&2 +		printf "cb/%s: Can't use U-Boot in text mode\n" "$target" 1>&2 +  		return 0  	elif [ "$initmode" = "normal" ]; then -		printf "cb/%s: Cannot use U-Boot in normal initmode\n" \ +		printf "cb/%s: Can't use U-Boot in normal initmode\n" \  		    "$target" 1>&2 +  		return 0  	fi @@ -220,54 +401,114 @@ add_uboot()  	# aarch64 targets:  	ubcbfsargs=""  	ubpath="fallback/payload" +	ubtree="default"  	ubtarget="$target" +  	# override for x86/x86_64 targets: -	if [ "$payload_uboot_i386" = "y" ] || \ -	    [ "$payload_uboot_amd64" = "y" ]; then +	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, and stub before that +			# 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" -		[ "$payload_uboot_i386" = "y" ] && ubpath="u-boot" # 32-bit -		[ "$payload_uboot_i386" = "y" ] && ubtarget="i386coreboot"; : + +		if [ "$payload_uboot" = "i386" ] +		then +			ubpath="u-boot" # 32-bit +			ubtree="x86" +			ubtarget="i386coreboot"; : +		fi  	fi -	ubdir="elf/u-boot/$ubtarget/$uboot_config" +	ubdir="elf/u-boot/$ubtree/$ubtarget/$uboot_config"  	# aarch64 targets: -	ubootelf="$ubdir/u-boot.elf" && [ ! -f "$ubootelf" ] && \ -	    ubootelf="$ubdir/u-boot" +	ubootelf="$ubdir/u-boot.elf" +	if [ ! -f "$ubootelf" ]; then +		ubootelf="$ubdir/u-boot" +	fi +  	# override for x86/x86_64 targets: -	[ "$payload_uboot_i386" = "y" ] && ubootelf="$ubdir/u-boot-dtb.bin" -	[ "$payload_uboot_amd64" = "y" ] && \ -	    ubootelf="$ubdir/u-boot-x86-with-spl.bin" # EFI-compatible +	if [ "$payload_uboot" = "i386" ]; then +		ubootelf="$ubdir/u-boot-dtb.bin" +	elif [ "$payload_uboot" = "amd64" ]; then +		ubootelf="$ubdir/u-boot-x86-with-spl.bin" # EFI-compatible +	fi -	[ -f "$ubootelf" ] || $err "cb/$ubtarget: Can't find u-boot"  	cbfs "$tmprom" "$ubootelf" "$ubpath" $ubcbfsargs -	[ "$payload_seabios" = "y" ] || cprom; : +	if [ "$payload_seabios" != "y" ]; then +		cprom +	fi  } +# 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" -	[ $# -gt 0 ] && [ "$1" != "seauboot" ] && \ -	    newrom="${newrom%.rom}_${1%.gkb}.rom" - -	x_ mkdir -p "bin/$target" -	x_ cp "$tmprom" "$newrom" && [ $# -gt 0 ] && [ "$1" != "seauboot" ] && \ -	    cbfs "$newrom" "config/data/grub/keymap/$1" keymap.gkb raw -	[ $# -gt 0 ] && [ "$1" = "seauboot" ] && \ -	    cbfs "$newrom" "config/data/grub/bootorder_uboot" bootorder raw; : + +	if [ -n "$displaymode" ]; then +		newrom="${newrom%.rom}_$displaymode.rom" +	fi +	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_ xbmkdir "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()  { -	[ "$target" = "$tree" ] && return 0 -	[ "$XBMK_RELEASE" = "y" ] || return 0 -	[ "$release" != "n" ] || return 0 -	$dry mkrom_tarball "bin/$target" -	$dry ./mk inject "bin/${relname}_${target}.tar.xz" nuke || \ -	    $err "Can't delete vendorfiles in 'bin/${relname}_$target.tar.xz'" -	return 0 +	$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 new file mode 100644 index 00000000..166a3d86 --- /dev/null +++ b/include/tree.sh @@ -0,0 +1,772 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +# Copyright (c) 2022-2023 Alper Nebi Yasak <alpernebiyasak@gmail.com> +# Copyright (c) 2022 Ferass El Hafidi <vitali64pmemail@protonmail.com> +# Copyright (c) 2023-2025 Leah Rowe <leah@libreboot.org> + +# 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="" + +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 +		if [ -n "$flag" ]; then +			err "only one flag is permitted" "trees" "$@" +		fi + +		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=":" +			if [ "$flag" = "-F" ]; then +				# don't skip git fetch/pull on cached src + +				forcepull="y" +			fi +			;; +		-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" +	if [ ! -f "$listfile" ]; then +		listfile="" # build.list is optional on all projects +	fi + +	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() +{ +	if ! configure_project "$configdir"; then +		return 0 +	elif [ -f "$listfile" ]; then +		if ! $if_not_dry_build elfcheck; then +			return 0 +		fi +	fi + +	if [ "$mode" = "distclean" ]; then +		mode="clean" +	fi + +	if ! run_make_command; then +		return 0 +	fi + +	if [ -z "$mode" ]; then +		$if_not_dry_build \ +			copy_elf; : +	fi +} + +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 + +		if [ -z "$mode" ]; then +			x_ $postmake +		fi +	done; : +} + +handle_defconfig() +{ +	target_dir="$configdir/$target" + +	if [ ! -f "CHANGELOG" ]; then +		fetch_project "$project" +	fi +	if ! configure_project "$target_dir"; then +		return 0 +	fi + +	if [ -z "$tree" ]; then +		err "$configdir: 'tree' not set" "handle_defconfig" "$@" +	fi + +	srcdir="src/$project/$tree" + +	if [ "$mode" = "${mode%clean}" ] && [ ! -d "$srcdir" ]; then +		return 0 +	fi + +	for y in "$target_dir/config"/* +	do +		if [ "$flag" != "-d" ] && [ ! -f "$y" ]; then +			continue +		elif [ "$flag" != "-d" ]; then +			defconfig="$y" +		fi + +		if [ -z "$mode" ]; then +			check_defconfig || continue; : +		fi + +		if [ -z "$mode" ]; then +			for _xarch in $xarch; do +				$if_dry_build \ +					break +				if [ -n "$_xarch" ]; then +					check_cross_compiler "$_xarch" +				fi +			done; : +		fi + +		handle_makefile + +		if [ -z "$mode" ]; then +			$if_not_dry_build \ +				copy_elf +		fi +	done; : +} + +configure_project() +{ +	_tcfg="$1/target.cfg" + +	autoconfargs="" +	badhash="" +	badtghash="" +	bootstrapargs="" +	build_depend="" +	buildtype="" +	cleanargs="" +	makeargs="" +	mkhelper="" +	postmake="" +	premake="" +	release="" +	xarch="" +	xgcctree="" +	xlang="" + +	if [ ! -f "$_tcfg" ]; then +		buildtype="auto" +	fi + +	# 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 +		# TODO: implement infinite loop detection here, caused +		#       by project targets pointing to other targets/trees +		#       when then ultimate point back repeatedly; this is +		#       currently avoided simply by careful configuration. +		#       temporary files per tree/target name could be created +		#	per iteration, and then checked the next time + +		printf "Loading %s config: %s\n" "$project" "$_tcfg" + +		rev="" +		tree="" + +		. "$_tcfg" || \ +		    err "Can't read '$_tcfg'" "configure_project" "$@" + +		if [ "$flag" = "-d" ]; then +			build_depend="" # dry run +		fi +		if [ "$cmd" = "build_project" ]; then +			# single-tree, so it can't be a target pointing +			# to a main source tree + +			break +		fi +		$if_do_make \ +			break +		if [ "${_tcfg%/*/target.cfg}" = "${_tcfg%"/$tree/target.cfg"}" ] +		then +			# we have found the main source tree that +			# a given target uses; no need to continue + +			break +		else +			_tcfg="${_tcfg%/*/target.cfg}/$tree/target.cfg" +		fi + +	done + +	if [ "$XBMK_RELEASE" = "y" ] && [ "$release" = "n" ]; then +		return 1 +	fi +	if [ -n "$buildtype" ] && [ "${mode%config}" != "$mode" ]; then +		return 1 +	fi + +	if [ -z "$mode" ]; then +		$if_not_dry_build \ +			build_dependencies +	fi + +	mdir="$xbmkpwd/config/submodule/$project" +	if [ -n "$tree" ]; then +		mdir="$mdir/$tree" +	fi + +	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##*/}" + +		if [ -z "$bd_project" ]; then +			$if_not_dry_build \ +				err "$project/$tree: !bd '$bd'" \ +				    "build_dependencies" "$@" +		fi +		if [ "${bd##*/}" = "$bd" ]; then +			bd_tree="" +		fi +		if [ -n "$bd_project" ]; then +			$if_not_dry_build \ +				x_ ./mk -b $bd_project $bd_tree; : +		fi +	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: +	if ! project_up_to_date hash "$tree" badhash "$datadir" \ +	    "$configdir/$tree" "$mdir"; then +		x_ rm -Rf "src/$project/$tree" "elf/$project/$tree" +	fi + +	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: + +	if ! project_up_to_date tghash "$target" badtghash "$configdir/$target" +	then +		x_ rm -Rf "elf/$project/$tree/$target" +	fi + +	x_ cp "$xbtmp/new.hash" "$XBMK_CACHE/tghash/$project$target" +} + +project_up_to_date() +{ +	old_hash="" +	hash="" + +	hashdir="$1" +	hashname="$2" +	badhashvar="$3" + +	shift 3 + +	x_ xbmkdir "$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" + +	if [ "$project" != "coreboot" ]; then +		cbdir="src/coreboot/default" +	fi +	if [ -n "$xgcctree" ]; then +		cbdir="src/coreboot/$xgcctree" +	fi + +	xfix="${1%-*}" + +	if [ "$xfix" = "x86_64" ]; then +		xfix="x64" +	fi + +	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_ xbmkdir "elf/coreboot/$tree" # TODO: is this needed? + +	export PATH="$xbmkpwd/$cbdir/util/crossgcc/xgcc/bin:$PATH" +	export CROSS_COMPILE="${xarch% *}-" + +	if [ -n "$xlang" ]; then +		export BUILD_LANGUAGES="$xlang" +	fi + +	if [ -f "$xgccfile" ]; then +		# skip the build, because a build already exists: + +		return 0 +	fi + +	check_gnu_path gcc gnat || x_ check_gnu_path gnat gcc +	make -C "$cbdir" $xgccargs || x_ make -C "$cbdir" $xgccargs + +	# this tells subsequent runs that the build was already done: +	x_ touch "$xgccfile" + +	# reset hostcc in PATH: +	remkdir "$xbtmp/gnupath" +} + +# 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() +{ +	if ! command -v "$1" 1>/dev/null; then +		err "Host '$1' unavailable" "check_gnu_path" "$@" +	fi + +	gccdir="" +	gccfull="" +	gccver="" +	gnatdir="" +	gnatfull="" +	gnatver="" + +	if host_gcc_gnat_match "$@"; then +		return 0 +	fi + +	if ! match_gcc_gnat_versions "$@"; then +		return 1 +	fi +} + +# check if gcc/gnat versions already match: + +host_gcc_gnat_match() +{ +	if ! gnu_setver "$1" "$1"; then +		err "Command '$1' unavailable." "check_gnu_path" "$@" +	fi +	gnu_setver "$2" "$2" || : + +	eval "[ -z \"\$$1ver\" ] && err \"Cannot detect host '$1' version\"" + +	if [ "$gnatfull" != "$gccfull" ]; then +		# non-matching gcc/gnat versions + +		return 1 +	fi +} + +# 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 + +	if ! gnu_setver "$2" "$_gnudir/$2-$_gnuver"; then +		return 1 +	elif [ "$gnatfull" != "$gccfull" ]; then +		return 1 +	fi + +	( 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##*/}" +		if [ -e "$_gnubin" ]; then +			x_ ln -s "$_gnubin" "${_gnuutil%"-$_gnuver"}" +		fi +	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() +{ +	if [ ! -f "$defconfig" ]; then +		$if_not_dry_build \ +			err "$project/$target: no config" "check_defconfig" "$@" +	fi + +	dest_dir="$elfdir/$tree/$target/${defconfig#"$target_dir/config/"}" + +	# skip build if a previous one exists: + +	$if_dry_build \ +		return 0 +	if ! elfcheck; then +		return 1 +	fi +} + +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 + +	if [ -f "$defconfig" ]; then +		x_ cp "$defconfig" "$srcdir/.config" +	fi + +	run_make_command || \ +	    err "no makefile!" "handle_makefile" "$@" + +	_copy=".config" + +	if [ "$mode" = "savedefconfig" ]; then +		_copy="defconfig" +	fi + +	if [ "${mode%config}" != "$mode" ]; then +		$if_not_dry_build \ +			x_ cp "$srcdir/$_copy" "$defconfig"; : +	fi + +	if [ -e "$srcdir/.git" ] && [ "$project" = "u-boot" ] && \ +	    [ "$mode" = "distclean" ]; then +		$if_not_dry_build \ +			x_ git -C "$srcdir" $cleanargs clean -fdx; : +	fi +} + +run_make_command() +{ +	if [ -z "$mode" ]; then +		x_ $premake +	fi + +	if $if_not_dry_build check_cmake "$srcdir"; then +		if [ -z "$mode" ]; then +			$if_not_dry_build \ +				check_autoconf "$srcdir" +		fi +	fi +	if ! $if_not_dry_build check_makefile "$srcdir"; then +		return 1 +	fi + +	$if_not_dry_build \ +		x_ make -C "$srcdir" $mode -j$XBMK_THREADS $makeargs + +	if [ -z "$mode" ]; then +		x_ $mkhelper +	fi + +	if ! check_makefile "$srcdir"; then +		return 0 +	fi + +	if [ "$mode" = "clean" ]; then +		$if_dry_build \ +			return 0 +		if ! make -C "$srcdir" $cleanargs distclean; then +			x_ make -C "$srcdir" $cleanargs clean +		fi +	fi +} + +check_cmake() +{ +	$if_dry_build \ +		return 0 +	if [ ! -n "$cmakedir" ]; then +		return 0 +	elif ! check_makefile "$1"; then +		if ! cmake -B "$1" "$1/$cmakedir"; then +			x_ check_makefile "$1" +		fi +	fi +	x_ check_makefile "$1"; : +} + +check_autoconf() +{ +	( +		x_ cd "$1" + +		if [ -f "bootstrap" ]; then +			x_ ./bootstrap $bootstrapargs +		fi +		if [ -f "autogen.sh" ]; then +			x_ ./autogen.sh $autogenargs +		fi +		if [ -f "configure" ]; then +			x_ ./configure $autoconfargs; : +		fi + +	) || err "can't bootstrap project: $1" "check_autoconf" "$@"; : +} + +check_makefile() +{ +	if [ ! -f "$1/Makefile" ] && [ ! -f "$1/makefile" ] && \ +	    [ ! -f "$1/GNUmakefile" ]; then + +		return 1 +	fi +} + +copy_elf() +{ +	if [ -f "$listfile" ]; then +		x_ xbmkdir "$dest_dir" +	fi + +	if [ -f "$listfile" ]; then +		while read -r f +		do +			if [ -f "$srcdir/$f" ]; then +				x_ cp "$srcdir/$f" "$dest_dir" +			fi + +		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 index 15d4e5cb..509cea8e 100644 --- a/include/vendor.sh +++ b/include/vendor.sh @@ -1,672 +1,735 @@  # SPDX-License-Identifier: GPL-3.0-only +  # Copyright (c) 2022 Caleb La Grange <thonkpeasant@protonmail.com>  # Copyright (c) 2022 Ferass El Hafidi <vitali64pmemail@protonmail.com>  # Copyright (c) 2023-2025 Leah Rowe <leah@libreboot.org> -e6400_unpack="$PWD/src/bios_extract/dell_inspiron_1100_unpacker.py" -me7updateparser="$PWD/util/me7_update_parser/me7_update_parser.py" -pfs_extract="$PWD/src/biosutilities/Dell_PFS_Extract.py" -uefiextract="$PWD/elf/uefitool/uefiextract" +# 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" -cbcfgsdir="config/coreboot" -hashfiles="vendorhashes blobhashes" # blobhashes for backwards compatibility -dontflash="!!! AN ERROR OCCURED! Please DO NOT flash if injection failed. !!!" -vfix="DO_NOT_FLASH_YET._FIRST,_INJECT_BLOBS_VIA_INSTRUCTIONS_ON_LIBREBOOT.ORG_" -vguide="https://libreboot.org/docs/install/ivy_has_common.html" -tmpromdel="$PWD/tmp/DO_NOT_FLASH" - -cv="CONFIG_HAVE_ME_BIN CONFIG_ME_BIN_PATH CONFIG_INCLUDE_SMSC_SCH5545_EC_FW \ -    CONFIG_SMSC_SCH5545_EC_FW_FILE CONFIG_KBC1126_FIRMWARE CONFIG_KBC1126_FW1 \ -    CONFIG_KBC1126_FW2 CONFIG_KBC1126_FW1_OFFSET CONFIG_KBC1126_FW2_OFFSET \ -    CONFIG_VGA_BIOS_FILE CONFIG_VGA_BIOS_ID CONFIG_BOARD_DELL_E6400 \ -    CONFIG_HAVE_MRC CONFIG_MRC_FILE CONFIG_HAVE_REFCODE_BLOB \ -    CONFIG_REFCODE_BLOB_FILE CONFIG_GBE_BIN_PATH CONFIG_IFD_BIN_PATH \ -    CONFIG_LENOVO_TBFW_BIN CONFIG_FSP_FD_PATH CONFIG_FSP_M_FILE \ -    CONFIG_FSP_S_FILE CONFIG_FSP_S_CBFS CONFIG_FSP_M_CBFS CONFIG_FSP_USE_REPO \ -    CONFIG_FSP_FULL_FD" - -eval "`setvars "" has_hashes EC_hash DL_hash DL_url_bkup MRC_refcode_gbe vcfg \ -    E6400_VGA_DL_hash E6400_VGA_DL_url E6400_VGA_DL_url_bkup E6400_VGA_offset \ -    E6400_VGA_romname SCH5545EC_DL_url_bkup SCH5545EC_DL_hash _dest tree \ -    mecleaner kbc1126_ec_dump MRC_refcode_cbtree new_mac _dl SCH5545EC_DL_url \ -    archive EC_url boarddir rom cbdir DL_url nukemode cbfstoolref FSPFD_hash \ -    _7ztest ME11bootguard ME11delta ME11version ME11sku ME11pch tmpromdir \ -    IFD_platform ifdprefix cdir sdir _me _metmp mfs TBFW_url_bkup TBFW_url \ -    TBFW_hash TBFW_size hashfile xromsize xchanged EC_url_bkup $cv`" - -vendor_download() +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 +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 in pkg.cfg files in config/vendor/ +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="" +MEclean="" +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()  { -	[ $# -gt 0 ] || $err "No argument given"; export PATH="$PATH:/sbin" -	board="$1"; readcfg && readkconfig && bootstrap && getfiles; : -} +	if [ $# -lt 1 ]; then +		err "No argument given" "download" "$@" +	fi -readkconfig() -{ -	check_defconfig "$boarddir" 1>"$TMPDIR/vendorcfg.list" && return 1 - -	rm -f "$TMPDIR/tmpcbcfg" || $err "!rm $TMPDIR/tmpcbcfg - $dontflash" -	while read -r cbcfgfile; do -		for cbc in $cv; do -			rm -f "$TMPDIR/tmpcbcfg2" || \ -			    $err "!rm $TMPDIR/tmpcbcfg2 - $dontflash" -			grep "$cbc" "$cbcfgfile" 1>"$TMPDIR/tmpcbcfg2" \ -			    2>/dev/null || : -			[ -f "$TMPDIR/tmpcbcfg2" ] || continue -			cat "$TMPDIR/tmpcbcfg2" >> "$TMPDIR/tmpcbcfg" || \ -			    $err "!cat $TMPDIR/tmpcbcfg2 - $dontflash" -		done -	done < "$TMPDIR/vendorcfg.list" - -	eval "`setcfg "$TMPDIR/tmpcbcfg"`" - -	for c in CONFIG_HAVE_MRC CONFIG_HAVE_ME_BIN CONFIG_KBC1126_FIRMWARE \ -	    CONFIG_VGA_BIOS_FILE CONFIG_INCLUDE_SMSC_SCH5545_EC_FW \ -	    CONFIG_LENOVO_TBFW_BIN CONFIG_FSP_M_FILE CONFIG_FSP_S_FILE; do -		eval "[ \"\${$c}\" = \"/dev/null\" ] && continue" -		eval "[ -z \"\${$c}\" ] && continue" -		eval "`setcfg "config/vendor/$vcfg/pkg.cfg"`"; return 0 -	done -	printf "Vendor files not needed for: %s\n" "$board" 1>&2; return 1 -} +	export PATH="$PATH:/sbin" +	board="$1" -bootstrap() -{ -	x_ ./mk -f coreboot ${cbdir##*/} -	mk -b uefitool biosutilities bios_extract -	[ -d "${kbc1126_ec_dump%/*}" ] && x_ make -C "$cbdir/util/kbc1126" -	[ -n "$MRC_refcode_cbtree" ] && \ -	    cbfstoolref="elf/cbfstool/$MRC_refcode_cbtree/cbfstool" && \ -	    x_ ./mk -d coreboot "$MRC_refcode_cbtree"; return 0 +	if check_target; then +		readkconfig download +	fi  }  getfiles()  { -	[ -z "$CONFIG_HAVE_ME_BIN" ] || fetch intel_me "$DL_url" \ -	    "$DL_url_bkup" "$DL_hash" "$CONFIG_ME_BIN_PATH" -	[ -z "$CONFIG_INCLUDE_SMSC_SCH5545_EC_FW" ] || fetch sch5545ec \ -	    "$SCH5545EC_DL_url" "$SCH5545EC_DL_url_bkup" "$SCH5545EC_DL_hash" \ -	    "$CONFIG_SMSC_SCH5545_EC_FW_FILE" -	[ -z "$CONFIG_KBC1126_FIRMWARE" ] || fetch kbc1126ec "$EC_url" \ -	    "$EC_url_bkup" "$EC_hash" "$CONFIG_KBC1126_FW1" -	[ -z "$CONFIG_VGA_BIOS_FILE" ] || fetch e6400vga "$E6400_VGA_DL_url" \ -	  "$E6400_VGA_DL_url_bkup" "$E6400_VGA_DL_hash" "$CONFIG_VGA_BIOS_FILE" -	[ -z "$CONFIG_HAVE_MRC" ] || fetch "mrc" "$MRC_url" "$MRC_url_bkup" \ -	    "$MRC_hash" "$CONFIG_MRC_FILE" -	[ -z "$CONFIG_LENOVO_TBFW_BIN" ] || fetch "tbfw" "$TBFW_url" \ -	    "$TBFW_url_bkup" "$TBFW_hash" "$CONFIG_LENOVO_TBFW_BIN" -	# -	# in the future, we might have libre fsp-s and then fsp-m. -	# therefore, handle them separately, in case one of them is libre; if -	# one of them was, the path wouldn't be set. -	# -	[ -z "$CONFIG_FSP_M_FILE" ] || fetch "fspm" "$CONFIG_FSP_FD_PATH" \ -	    "$CONFIG_FSP_FD_PATH" "$FSPFD_hash" "$CONFIG_FSP_M_FILE" copy -	[ -z "$CONFIG_FSP_S_FILE" ] || fetch "fsps" "$CONFIG_FSP_FD_PATH" \ -	    "$CONFIG_FSP_FD_PATH" "$FSPFD_hash" "$CONFIG_FSP_S_FILE" copy; : +	if [ -n "$CONFIG_HAVE_ME_BIN" ];then +		fetch intel_me "$DL_url" "$DL_url_bkup" "$DL_hash" \ +		    "$CONFIG_ME_BIN_PATH" curl "$ME_bin_hash" +	fi +	if [ -n "$CONFIG_INCLUDE_SMSC_SCH5545_EC_FW" ]; then +		fetch sch5545ec "$SCH5545EC_DL_url" "$SCH5545EC_DL_url_bkup" \ +		    "$SCH5545EC_DL_hash" "$CONFIG_SMSC_SCH5545_EC_FW_FILE" \ +		    "curl" "$SCH5545EC_bin_hash" +	fi +	if [ -n "$CONFIG_KBC1126_FW1" ]; then +		fetch kbc1126ec "$EC_url" "$EC_url_bkup" "$EC_hash" \ +		    "$CONFIG_KBC1126_FW1" curl "$EC_FW1_hash" +	fi +	if [ -n "$CONFIG_KBC1126_FW2" ]; then +		fetch kbc1126ec "$EC_url" "$EC_url_bkup" "$EC_hash" \ +		    "$CONFIG_KBC1126_FW2" curl "$EC_FW2_hash" +	fi +	if [ -n "$CONFIG_VGA_BIOS_FILE" ]; then +		fetch e6400vga "$E6400_VGA_DL_url" "$E6400_VGA_DL_url_bkup" \ +		    "$E6400_VGA_DL_hash" "$CONFIG_VGA_BIOS_FILE" "curl" \ +		    "$E6400_VGA_bin_hash" +	fi +	if [ -n "$CONFIG_HAVE_MRC" ]; then +		fetch "mrc" "$MRC_url" "$MRC_url_bkup" "$MRC_hash" \ +		    "$CONFIG_MRC_FILE" "curl" "$MRC_bin_hash" +	fi +	if [ -n "$CONFIG_REFCODE_BLOB_FILE" ]; then +		fetch "refcode" "$MRC_url" "$MRC_url_bkup" "$MRC_hash" \ +		    "$CONFIG_REFCODE_BLOB_FILE" "curl" "$REF_bin_hash" +	fi +	if [ -n "$CONFIG_LENOVO_TBFW_BIN" ]; then +		fetch "tbfw" "$TBFW_url" "$TBFW_url_bkup" "$TBFW_hash" \ +		    "$CONFIG_LENOVO_TBFW_BIN" "curl" "$TBFW_bin_hash" +	fi +	if [ -n "$CONFIG_FSP_M_FILE" ]; then +		fetch "fsp" "$CONFIG_FSP_FD_PATH" "$CONFIG_FSP_FD_PATH" \ +		    "$FSPFD_hash" "$CONFIG_FSP_M_FILE" "copy" "$FSPM_bin_hash" +	fi +	if [ -n "$CONFIG_FSP_S_FILE" ]; then +		fetch "fsp" "$CONFIG_FSP_FD_PATH" "$CONFIG_FSP_FD_PATH" \ +		    "$FSPFD_hash" "$CONFIG_FSP_S_FILE" "copy" "$FSPS_bin_hash" +	fi  }  fetch()  { -	dl_type="$1"; dl="$2"; dl_bkup="$3"; dlsum="$4"; _dest="${5##*../}" -	[ "$5" = "/dev/null" ] && return 0; _dl="$XBMK_CACHE/file/$dlsum" -	if [ "$dl_type" = "fspm" ] || [ "$dl_type" = "fsps" ]; then -		# HACK: if grabbing fsp from coreboot, fix the path for lbmk -		for _cdl in dl dl_bkup; do -			eval "$_cdl=\"\${$_cdl##*../}\"; _cdp=\"\$$_cdl\"" -			[ -f "$_cdp" ] || _cdp="$cbdir/$_cdp" -			[ -f "$_cdp" ] && eval "$_cdl=\"$_cdp\"" -		done -	fi - -	dlop="curl" && [ $# -gt 5 ] && dlop="$6" -	download "$dl" "$dl_bkup" "$_dl" "$dlsum" "$dlop" - -	rm -Rf "${_dl}_extracted" || $err "!rm ${_ul}_extracted. $dontflash" -	e "$_dest" f && return 0 - -	mkdir -p "${_dest%/*}" || \ -	    $err "mkdirs: !mkdir -p ${_dest%/*} - $dontflash" -	remkdir "$appdir"; extract_archive "$_dl" "$appdir" "$dl_type" || \ -	    [ "$dl_type" = "e6400vga" ] || \ -	    $err "mkd $_dest $dl_type: !extract. $dontflash" - -	eval "extract_$dl_type"; set -u -e -	e "$_dest" f missing && $err "!extract_$dl_type. $dontflash"; : +	dl_type="$1" +	dl="$2" +	dl_bkup="$3" +	dlsum="$4" +	_dest="${5##*../}" +	_pre_dest="$XBMK_CACHE/tmpdl/check" +	dlop="$6" +	binsum="$7" + +	if [ -z "$binsum" ]; then +		err "binsum is empty (no checksum)" "fetch" "$@" +	fi + +	_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 + +	if [ "$5" = "/dev/null" ]; then +		return 0 +	fi + +	# 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" + +		if [ ! -f "$_cdp" ]; then +			_cdp="$cbdir/$_cdp" +		fi +		if [ -f "$_cdp" ]; then +			dl="$_cdp" +		fi + +		dl_bkup="${dl_bkup##*../}" +		_cdp="$dl_bkup" + +		if [ ! -f "$_cdp" ]; then +			_cdp="$cbdir/$_cdp" +		fi +		if [ -f "$_cdp" ]; then +			dl_bkup="$_cdp"; : +		fi +	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 ) || : +	if [ -f "$_dest" ]; then +		return 0 +	fi + +	x_ xbmkdir "${_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 ) || : + +	if ! bad_checksum "$binsum" "$_dest"; then +		if [ -f "$_dest" ]; then +			return 0 +		fi +	fi + +	if [ -z "$binsum" ]; then +		printf "'%s': checksum undefined\n" "$_dest" 1>&2 +	fi + +	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()  { -	e "$mecleaner" f not && $err "$cbdir: me_cleaner missing. $dontflash" - -	cdir="$PWD/$appdir" -	_me="$PWD/$_dest" -	_metmp="$PWD/tmp/me.bin" +	if e "$mecleaner" f missing; then +		err "$cbdir: me_cleaner missing" "extract_intel_me" "$@" +	fi -	mfs="" && [ "$ME11bootguard" = "y" ] && mfs="--whitelist MFS" && \ -	    chkvars ME11delta ME11version ME11sku ME11pch -	[ "$ME11bootguard" = "y" ] && x_ ./mk -f deguard +	mfs="" +	_7ztest="$xbtmp/metmp/a" +	_metmp="$xbtmp/me.bin" -	x_ mkdir -p tmp +	x_ rm -f "$_metmp" "$xbtmp/a" +	x_ rm -Rf "$_7ztest" -	extract_intel_me_bruteforce  	if [ "$ME11bootguard" = "y" ]; then -		apply_me11_deguard_mod +		mfs="--whitelist MFS" + +		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 -		mv "$_metmp" "$_me" || $err "!mv $_metmp $_me - $dontflash" +		( apply_deguard_hack ) || \ +		    err "deguard error on '$_dest'" "extract_intel_me" "$@"; :  	fi  } -extract_intel_me_bruteforce() +# bruteforce Intel ME extraction. +# must be called inside a subshell. +find_me()  { -	[ $# -gt 0 ] && cdir="$1" +	if [ -f "$_metmp" ]; then +		# we found me.bin, so we stop searching -	e "$_metmp" f && return 0 +		exit 1 +	elif [ -L "$1" ]; then +		return 0 +	fi -	[ -z "$sdir" ] && sdir="$(mktemp -d)" -	mkdir -p "$sdir" || \ -	    $err "extract_intel_me: !mkdir -p \"$sdir\" - $dontflash" +	_7ztest="${_7ztest}a" -	set +u +e -	( -	[ "${cdir#/a}" != "$cdir" ] && cdir="${cdir#/}" -	cd "$cdir" || $err "extract_intel_me: !cd \"$cdir\" - $dontflash" -	for i in *; do -		[ -f "$_metmp" ] && break -		[ -L "$i" ] && continue -		if [ -f "$i" ]; then -			_r="-r" && [ -n "$mfs" ] && _r="" -			"$mecleaner" $mfs $_r -t -O "$sdir/vendorfile" \ -			    -M "$_metmp" "$i" && break -			"$mecleaner" $mfs $_r -t -O "$_metmp" "$i" && break -			"$me7updateparser" -O "$_metmp" "$i" && break -			_7ztest="${_7ztest}a" -			extract_archive "$i" "$_7ztest" || continue -			extract_intel_me_bruteforce "$cdir/$_7ztest" -		elif [ -d "$i" ]; then -			extract_intel_me_bruteforce "$cdir/$i" -		else -			continue -		fi -		cdir="$1"; [ "${cdir#/a}" != "$cdir" ] && cdir="${cdir#/}" -		cd "$cdir" || : -	done -	) -	rm -Rf "$sdir" || $err "extract_intel_me: !rm -Rf $sdir - $dontflash" +	_keep="" # -k: keep fptr modules even if they can be removed +	_pass="" # -p: skip fptr check +	_r="-r" # re-locate modules +	_trunc="-t" # -t: truncate the ME size + +	if [ -n "$mfs" ] || [ "$MEclean" = "n" ]; then +		_r="" +	fi + +	if [ "$MEclean" = "n" ]; then +		_keep="-k" +		_pass="-p" +		_trunc="" +	fi + +	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 +		# could not extract anything, so we'll try the next file +		return 0 +	fi + +	if [ -f "$_metmp" ]; then +		# we found me.bin, so we stop searching + +		exit 1 +	else +		# if the subshell does exit 1, we found me.bin, so exit 1 +		( fx_ find_me x_ find "$_7ztest" -type f ) || exit 1; : +	fi  } -apply_me11_deguard_mod() +apply_deguard_hack()  { -	( -	x_ cd src/deguard/ -	./finalimage.py --delta "data/delta/$ME11delta" \ -	    --version "$ME11version" \ -	    --pch "$ME11pch" --sku "$ME11sku" --fake-fpfs data/fpfs/zero \ -	    --input "$_metmp" --output "$_me" || \ -	    $err "Error running deguard for $_me - $dontflash" -	) || $err "Error running deguard for $_me - $dontflash" +	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()  { -	if [ $# -gt 2 ]; then -		if [ "$3" = "fspm" ] || [ "$3" = "fsps" ]; then -			decat_fspfd "$1" "$2" -			return 0 -		fi +	if innoextract "$1" -d "$2"; then +		: +	elif python "$pfs_extract" "$1" -e; then +		: +	elif 7z x "$1" -o"$2"; then +		: +	elif "$bsdtar" -C "$2" -xf "$1"; then +		: +	elif "$bsdunzip" "$1" -d "$2"; then +		: +	else +		return 1  	fi -	innoextract "$1" -d "$2" || python "$pfs_extract" "$1" -e || 7z x \ -	    "$1" -o"$2" || unar "$1" -o "$2" || unzip "$1" -d "$2" || return 1 - -	[ ! -d "${_dl}_extracted" ] || cp -R "${_dl}_extracted" "$2" || \ -	    $err "!mv '${_dl}_extracted' '$2' - $dontflash"; : +	if [ -d "${_dl}_extracted" ]; then +		x_ cp -R "${_dl}_extracted" "$2" +	fi  } -decat_fspfd() +extract_kbc1126ec()  { -	_fspfd="$1" -	_fspdir="$2" -	_fspsplit="$cbdir/3rdparty/fsp/Tools/SplitFspBin.py" +	( extract_kbc1126ec_dump ) || \ +	    err "$board: can't extract kbc1126 fw" "extract_kbc1126ec" "$@" -	$python "$_fspsplit" split -f "$_fspfd" -o "$_fspdir" -n "Fsp.fd" || \ -	    $err "decat_fspfd '$1' '$2': Can't de-concatenate; $dontflash"; : +	# 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() +extract_kbc1126ec_dump()  { -	e "$kbc1126_ec_dump" f missing && \ -	    $err "$cbdir: kbc1126 util missing - $dontflash" -	( -	x_ cd "$appdir/"; mv Rompaq/68*.BIN ec.bin || : +	x_ cd "$appdir/" + +	if mv Rompaq/68*.BIN ec.bin; then +		: +	elif unar -D ROM.CAB Rom.bin; then +		: +	elif unar -D Rom.CAB Rom.bin; then +		: +	elif unar -D 68*.CAB Rom.bin; then +		: +	else +		err "!kbc1126 unar" "extract_kbc1126ec" "$@" +	fi +  	if [ ! -f "ec.bin" ]; then -		unar -D ROM.CAB Rom.bin || unar -D Rom.CAB Rom.bin || \ -		    unar -D 68*.CAB Rom.bin || \ -		    $err "can't extract Rom.bin - $dontflash"  		x_ mv Rom.bin ec.bin  	fi -	[ -f ec.bin ] || \ -	    $err "extract_kbc1126_ec $board: can't extract - $dontflash" -	"$kbc1126_ec_dump" ec.bin || \ -	    $err "!1126ec $board extract ecfw - $dontflash" -	) || $err "can't extract kbc1126 ec firmware - $dontflash" - -	e "$appdir/ec.bin.fw1" f not && \ -	    $err "$board: kbc1126ec fetch failed - $dontflash" -	e "$appdir/ec.bin.fw2" f not && \ -	    $err "$board: kbc1126ec fetch failed - $dontflash" -	cp "$appdir/"ec.bin.fw* "${_dest%/*}/" || \ -	    $err "!cp 1126ec $_dest - $dontflash"; : +	if x_ e ec.bin f; then +		x_ "$kbc1126_ec_dump" ec.bin +	fi  }  extract_e6400vga()  {  	set +u +e -	chkvars E6400_VGA_offset E6400_VGA_romname + +	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" -	[ -f "bios.bin" ] || \ -	    $err "extract_e6400vga: can't extract bios.bin - $dontflash" +	x_ e "bios.bin" f  	"$e6400_unpack" bios.bin || printf "TODO: fix dell extract util\n" -	) || $err "can't extract e6400 vga rom - $dontflosh" -	cp "$appdir/$E6400_VGA_romname" "$_dest" || \ -	    $err "extract_e6400vga $board: can't cp $_dest - $dontflash"; : +	) || err "can't extract e6400 vga rom" "extract_e6400vga" "$@" + +	x_ cp "$appdir/$E6400_VGA_romname" "$_pre_dest"  }  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! -	"$uefiextract" "$_bios" || $err "sch5545 !extract - $dontflash" -	cp "$_sch5545ec_fw" "$_dest" || \ -	    $err "$_dest: !sch5545 copy - $dontflash"; : +	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()  { -	chkvars TBFW_size # size in bytes, matching TBFW's flash IC -	x_ mkdir -p tmp -	x_ rm -f tmp/tb.bin -	find "$appdir" -type f -name "TBT.bin" > "tmp/tb.txt" || \ -	    $err "extract_tbfw $_dest: Can't extract TBT.bin - $dontflash" -	while read -r f; do -		[ -f "$f" ] || continue -		[ -L "$f" ] && continue -		cp "$f" "tmp/tb.bin" || \ -		    $err "extract_tbfw $_dest: Can't copy TBT.bin - $dontflash" -		break -	done < "tmp/tb.txt" -	dd if=/dev/null of=tmp/tb.bin bs=1 seek=$TBFW_size || \ -	    $err "extract_tbfw $_dest: Can't pad TBT.bin - $dontflash" -	cp "tmp/tb.bin" "$_dest" || \ -	    $err "extract_tbfw $_dest: copy error - $dontflash "; : -} +	if [ -z "$TBFW_size" ]; then +		err "$board: TBFW_size unset" "extract_tbfw" "$@" +	fi -extract_fspm() -{ -	copy_fsp M; : +	fx_ copytb x_ find "$appdir" -type f -name "TBT.bin"  } -extract_fsps() +copytb()  { -	copy_fsp S; : -} +	if [ -f "$1" ] && [ ! -L "$1" ]; then +		x_ dd if=/dev/null of="$1" bs=1 seek=$TBFW_size +		x_ mv "$1" "$_pre_dest" -# this copies the fsp s/m; re-base is handled by ./mk inject -copy_fsp() -{ -	cp "$appdir/Fsp_$1.fd" "$_dest" || \ -	    $err "copy_fsp: Can't copy $1 to $_dest - $dontflash"; : +		return 1 +	fi  } -fail_inject() +extract_fsp()  { -	[ -L "$tmpromdel" ] || [ ! -d "$tmpromdel" ] || \ -	    rm -Rf "$tmpromdel" || : -	printf "\n\n%s\n\n" "$dontflash" 1>&2 -	printf "WARNING: File '%s' was NOT modified.\n\n" "$archive" 1>&2 -	printf "Please MAKE SURE vendor files are inserted before flashing\n\n" -	fail "$1" +	x_ python "$cbdir/3rdparty/fsp/Tools/SplitFspBin.py" split -f "$1" \ +	    -o "${_pre_dest%/*}" -n "Fsp.fd"  } -vendor_inject() +setvfile()  { -	_olderr="$err" -	err="fail_inject" -	remkdir "$tmpromdel" - -	set +u +e; [ $# -lt 1 ] && $err "No options specified. - $dontflash" -	eval "`setvars "" nukemode new_mac xchanged`" - -	archive="$1"; -	[ $# -gt 1 ] && case "$2" in -	nuke) nukemode="nuke" ;; -	setmac) -		new_mac="??:??:??:??:??:??" -		[ $# -gt 2 ] && new_mac="$3" ;; -	*) $err "Unrecognised inject mode: '$2'" -	esac - -	check_release "$archive" || \ -	    $err "You must run this script on a release archive. - $dontflash" -	if readcfg; then -		[ "$nukemode" = "nuke" ] || x_ ./mk download "$board" -		patch_release_roms -	else -		printf "Tarball '%s' (board '%s) doesn't need vendorfiles.\n" \ -		    "$archive" "$board" -		err="$_olderr" -		return 0 -	fi +	[ -n "$vcfg" ] && for c in $checkvarschk +	do +		do_getvfile="n" +		vcmd="[ \"\${$c}\" != \"/dev/null\" ] && [ -n \"\${$c}\" ]" -	xtype="patched" && [ "$nukemode" = "nuke" ] && xtype="nuked" -	[ "$xchanged" = "y" ] || \ -		printf "\nRelease archive '%s' was not modified.\n" "$archive" -	[ "$xchanged" = "y" ] && \ -		printf "\nRelease archive '%s' successfully %s.\n" \ -		    "$archive" "$xtype" -	[ "$xchanged" = "y" ] && [ "$nukemode" = "nuke" ] && \ -		printf "!!!WARNING!!! -> Vendor files removed. DO NOT FLASH.\n" -	err="$_olderr" -	return 0 -} +		eval "$vcmd && do_getvfile=\"y\"" -check_release() -{ -	[ -L "$archive" ] && \ -	    $err "'$archive' is a symlink, not a file - $dontflash" -	[ -f "$archive" ] || return 1 -	archivename="`basename "$archive"`" -	[ -z "$archivename" ] && \ -	    $err "Cannot determine archive file name - $dontflash" - -	case "$archivename" in -	*_src.tar.xz) -		$err "'$archive' is a src archive, silly!" ;; -	grub_*|seagrub_*|custom_*|seauboot_*|seabios_withgrub_*) -		return 1 ;; -	*.tar.xz) _stripped_prefix="${archivename#*_}" -		board="${_stripped_prefix%.tar.xz}" ;; -	*) $err "'$archive': could not detect board type - $dontflash" -	esac; : +		if [ "$do_getvfile" = "y" ]; then +			if getvfile "$@"; then +				return 0 +			fi +		fi +	done && return 1; :  } -readcfg() +getvfile()  { -	if [ "$board" = "serprog_rp2040" ] || \ -	    [ "$board" = "serprog_stm32" ] || \ -	    [ "$board" = "serprog_pico" ]; then +	if e "config/vendor/$vcfg/pkg.cfg" f missing; then  		return 1 -	fi; boarddir="$cbcfgsdir/$board" -	eval "`setcfg "$boarddir/target.cfg"`"; chkvars vcfg tree +	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 -	cbdir="src/coreboot/$tree" -	cbfstool="elf/cbfstool/$tree/cbfstool" -	rmodtool="elf/cbfstool/$tree/rmodtool" -	mecleaner="$PWD/$cbdir/util/me_cleaner/me_cleaner.py" -	kbc1126_ec_dump="$PWD/$cbdir/util/kbc1126/kbc1126_ec_dump" -	cbfstool="elf/cbfstool/$tree/cbfstool" -	ifdtool="elf/ifdtool/$tree/ifdtool" -	[ -n "$IFD_platform" ] && ifdprefix="-p $IFD_platform" - -	x_ ./mk -d coreboot "$tree"  } -patch_release_roms() +bootstrap()  { -	has_hashes="n" - -	tmpromdir="tmp/DO_NOT_FLASH/bin/$board" -	remkdir "${tmpromdir%"/bin/$board"}" -	tar -xf "$archive" -C "${tmpromdir%"/bin/$board"}" || \ -		$err "Can't extract '$archive'" - -	for _hashes in $hashfiles; do -		[ -L "$tmpromdir/$_hashes" ] && \ -		    $err "'$archive' -> the hashfile is a symlink. $dontflash" -		[ -f "$tmpromdir/$_hashes" ] && has_hashes="y" && \ -		    hashfile="$_hashes" && break; : -	done - -	x_ mkdir -p "tmp"; [ -L "tmp/rom.list" ] && \ -	    $err "'$archive' -> tmp/rom.list is a symlink - $dontflash" -	x_ rm -f "tmp/rom.list" "tmp/zero.1b" -	x_ dd if=/dev/zero of=tmp/zero.1b bs=1 count=1 - -	find "$tmpromdir" -maxdepth 1 -type f -name "*.rom" > "tmp/rom.list" \ -	    || $err "'$archive' -> Can't make tmp/rom.list - $dontflash" - -	if readkconfig; then -		while read -r _xrom ; do -			process_release_rom "$_xrom" || break -		done < "tmp/rom.list" -		rm -f "$tmpromdir/README.md" || : -		[ "$nukemode" != "nuke" ] || \ -		    printf "Make sure you inserted vendor files: %s\n" \ -		    "$vguide" > "$tmpromdir/README.md" || : -	else -		printf "Skipping vendorfiles on '%s'\n" "$archive" 1>&2 +	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" +	if [ "$XBMKmecleaner" = "y" ]; then +		mecleaner="$xbmkpwd/src/me_cleaner/me_cleaner.py"  	fi -	( -	cd "$tmpromdir" || $err "patch '$archive': can't cd $tmpromdir" -	# NOTE: For compatibility with older rom releases, defer to sha1 -	if [ "$has_hashes" = "y" ] && [ "$nukemode" != "nuke" ]; then -		sha512sum --status -c "$hashfile" || \ -		    sha1sum --status -c "$hashfile" || \ -		    $err "'$archive' -> Can't verify vendor hashes. $dontflash" -		rm -f "$hashfile" || \ -		    $err "$archive: Can't rm hashfile. $dontflash" -	fi -	) || $err "'$archive' -> Can't verify vendor hashes. $dontflash" - -	if [ -n "$new_mac" ]; then -		if ! modify_mac_addresses; then -			printf "\nNo GbE region defined for '%s'\n" "$board" \ -			    1>&2 -			printf "Therefore, changing the MAC is impossible.\n" \ -			    1>&2 -			printf "This board probably lacks Intel ethernet.\n" \ -			    1>&2 -		fi +	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 + +	if [ -d "${kbc1126_ec_dump%/*}" ]; then +		x_ make -C "$cbdir/util/kbc1126"  	fi -	[ "$xchanged" = "y" ] || rm -Rf "$tmpromdel" || : -	[ "$xchanged" = "y" ] || return 0 -	( -		cd "${tmpromdir%"/bin/$board"}" || \ -		    $err "Can't cd '${tmpromdir%"/bin/$board"}'; $dontflash" -		# ../../ is the root of lbmk -		mkrom_tarball "bin/$board" -	) || $err "Cannot re-generate '$archive' - $dontflash" - -	mv "${tmpromdir%"/bin/$board"}/bin/${relname}_${board}.tar.xz" \ -	    "$archive" || \ -	    $err "'$archive' -> Cannot overwrite - $dontflash"; : +	if [ -n "$MRC_refcode_cbtree" ]; then +		cbfstoolref="elf/coreboot/$MRC_refcode_cbtree/cbfstool" +		x_ ./mk -d coreboot "$MRC_refcode_cbtree"; : +	fi  } -process_release_rom() +prep()  { -	_xrom="$1"; _xromname="${1##*/}" -	[ -L "$_xrom" ] && \ -	    $err "$archive -> '${_xrom#"tmp/DO_NOT_FLASH/"}' is a symlink" -	[ -f "$_xrom" ] || return 0 +	_xrom="$1" +	_xromname="${1##*/}" +	_xromnew="${_xrom%/*}/${_xromname#"$vfix"}" + +	if [ "$nuke" = "nuke" ]; then +		_xromnew="${_xrom%/*}/$vfix${_xrom##*/}" +	fi + +	if e "$_xrom" f missing; then +		return 0 +	fi + +	if [ -z "${_xromname#"$vfix"}" ]; then +		err "$_xromname / $vfix: name match" "prep" "$@" +	fi -	[ -z "${_xromname#"$vfix"}" ] && \ -	    $err "'$_xromname'->'"${_xromname#"$vfix"}"' empty. $dontflash"  	# Remove the prefix and 1-byte pad -	if [ "$nukemode" != "nuke" ] && \ -	    [ "${_xromname#"$vfix"}" != "$_xromname" ]; then -		_xromnew="${_xrom%/*}/${_xromname#"$vfix"}" - -		# Remove the 1-byte padding -		stat -c '%s' "$_xrom" > "tmp/rom.size" || \ -		    $err "$_xrom: Can't get rom size. $dontflash" -		read -r xromsize < "tmp/rom.size" || \ -		    $err "$_xrom: Can't read rom size. $dontflash" - -		expr "X$xromsize" : "X-\{0,1\}[0123456789][0123456789]*$" \ -		    1>/dev/null 2>/dev/null || $err "$_xrom size non-integer" -		[ $xromsize -lt 2 ] && $err \ -		    "$_xrom: Will not create empty file. $dontflash" - -		# TODO: check whether the size would be a multiple of 64KB -		# the smallest rom images we do are 512kb	 -		xromsize="`expr $xromsize - 1`" -		[ $xromsize -lt 524288 ] && \ -		    $err "$_xrom size too small; likely not a rom. $dontflash" - -		dd if="$_xrom" of="$_xromnew" bs=$xromsize count=1 || \ -		    $err "$_xrom: Can't resize. $dontflash" -		rm -f "$_xrom" || $err "Can't rm $_xrom - $dontflash" +	if [ "${_xromname#"$vfix"}" != "$_xromname" ] \ +	    && [ "$nuke" != "nuke" ]; then + +		unpad_one_byte "$_xrom" +		x_ mv "$_xrom" "$_xromnew"  		_xrom="$_xromnew"  	fi -	[ "$nukemode" = "nuke" ] && \ -		mksha512sum "$_xrom" "vendorhashes" +	if [ "$nuke" = "nuke" ]; then +		( mksha512 "$_xrom" "vendorhashes" ) || err; : +	fi + +	if ! add_vfiles "$_xrom"; then +		# no need to insert files. we will later +		# still process MAC addresses as required + +		return 1 +	fi + +	if [ "$nuke" = "nuke" ]; then +		pad_one_byte "$_xrom" +		x_ mv "$_xrom" "$_xromnew" +	fi +} + +mksha512() +{ +	build_sbase -	patch_rom "$_xrom" || return 1 # if break return, can still change MAC -	[ "$nukemode" != "nuke" ] && return 0 +	if [ "${1%/*}" != "$1" ]; then +		x_ cd "${1%/*}" +	fi -	# Rename the file, prefixing a warning saying not to flash -	# the target image, which now has vendor files removed. Also -	# pad it so that flashprog returns an error if the user tries -	# to flash it, due to mismatching ROM size vs chip size -	cat "$_xrom" tmp/zero.1b > "${_xrom%/*}/$vfix${_xrom##*/}" || \ -	    $err "'$archive' -> can't pad/rename '$_xrom'. $dontflash" -	rm -f "$_xrom" || $err "'$archive' -> can't rm '$_xrom'. $dontflash" +	x_ "$sha512sum" ./"${1##*/}" >> "$2" || \ +	    err "!sha512sum \"$1\" > \"$2\"" "mksha512" "$@"  } -patch_rom() +add_vfiles()  {  	rom="$1" -	if [ "$has_hashes" != "y" ] && [ "$nukemode" != "nuke" ]; then -		printf "inject: '%s' has no hash file. Skipping.\n" \ -		    "$archive" 1>&2 +	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" ] && inject "fallback/refcode" \ -	    "$CONFIG_REFCODE_BLOB_FILE" "stage" -	[ "$CONFIG_HAVE_MRC" = "y" ] && inject "mrc.bin" "$CONFIG_MRC_FILE" \ -	    "mrc" "0xfffa0000" -	[ "$CONFIG_HAVE_ME_BIN" = "y" ] && inject IFD "$CONFIG_ME_BIN_PATH" me -	[ "$CONFIG_KBC1126_FIRMWARE" = "y" ] && inject ecfw1.bin \ -	    "$CONFIG_KBC1126_FW1" raw "$CONFIG_KBC1126_FW1_OFFSET" && inject \ -	    ecfw2.bin "$CONFIG_KBC1126_FW2" raw "$CONFIG_KBC1126_FW2_OFFSET" -	[ -n "$CONFIG_VGA_BIOS_FILE" ] && [ -n "$CONFIG_VGA_BIOS_ID" ] && \ -	  inject "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" ] && \ -		inject sch5545_ecfw.bin "$CONFIG_SMSC_SCH5545_EC_FW_FILE" raw -	# -	# coreboot adds FSP-M first. so we shall add it first, then S: -	# NOTE: -	# We skip the fetch if CONFIG_FSP_USE_REPO or CONFIG_FSP_FULL_FD is set -	# but only for inject/nuke. we still run fetch (see above) because on -	# _fsp targets, coreboot still needs them, but coreboot Kconfig uses -	# makefile syntax and puts $(obj) in the path, which makes no sense -	# in sh. So we modify the path there, but lbmk only uses the file -	# in vendorfiles/ if neither CONFIG_FSP_USE_REPO nor CONFIG_FSP_FULL_FD -	# are set -	# -	[ -z "$CONFIG_FSP_USE_REPO" ] && [ -z "$CONFIG_FSP_FULL_FD" ] && \ -	   [ -n "$CONFIG_FSP_M_FILE" ] && \ -		inject "$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" ] && \ -		inject "$CONFIG_FSP_S_CBFS" "$CONFIG_FSP_S_FILE" fsp -	# TODO: modify gbe *after checksum verification only* -	# TODO: insert default gbe if doing -n nuke +	if [ -n "$CONFIG_HAVE_REFCODE_BLOB" ]; then +		vfile "fallback/refcode" "$CONFIG_REFCODE_BLOB_FILE" "stage" +	fi +	if [ "$CONFIG_HAVE_MRC" = "y" ]; then +		vfile "mrc.bin" "$CONFIG_MRC_FILE" "mrc" "0xfffa0000" +	fi +	if [ "$CONFIG_HAVE_ME_BIN" = "y" ]; then +		vfile IFD "$CONFIG_ME_BIN_PATH" me +	fi +	if [ -n "$CONFIG_KBC1126_FW1" ]; then +		vfile ecfw1.bin "$CONFIG_KBC1126_FW1" raw \ +		    "$CONFIG_KBC1126_FW1_OFFSET" +	fi +	if [ -n "$CONFIG_KBC1126_FW2" ]; then +		vfile ecfw2.bin "$CONFIG_KBC1126_FW2" raw \ +		    "$CONFIG_KBC1126_FW2_OFFSET" +	fi +	if [ -n "$CONFIG_VGA_BIOS_FILE" ] && [ -n "$CONFIG_VGA_BIOS_ID" ]; then +		vfile "pci$CONFIG_VGA_BIOS_ID.rom" "$CONFIG_VGA_BIOS_FILE" \ +		    optionrom +	fi +	if [ "$CONFIG_INCLUDE_SMSC_SCH5545_EC_FW" = "y" ] && \ +	    [ -n "$CONFIG_SMSC_SCH5545_EC_FW_FILE" ]; then +		vfile sch5545_ecfw.bin "$CONFIG_SMSC_SCH5545_EC_FW_FILE" raw +	fi +	if [ -z "$CONFIG_FSP_USE_REPO" ] && [ -z "$CONFIG_FSP_FULL_FD" ] && \ +	    [ -n "$CONFIG_FSP_M_FILE" ]; then +		vfile "$CONFIG_FSP_M_CBFS" "$CONFIG_FSP_M_FILE" fsp --xip +	fi +	if [ -z "$CONFIG_FSP_USE_REPO" ] && [ -z "$CONFIG_FSP_FULL_FD" ] && \ +	   [ -n "$CONFIG_FSP_S_FILE" ]; then +		vfile "$CONFIG_FSP_S_CBFS" "$CONFIG_FSP_S_FILE" fsp +	fi + +	xchanged="y"  	printf "ROM image successfully patched: %s\n" "$rom" -	xchanged="y"  } -inject() +vfile()  { -	[ $# -lt 3 ] && $err "$*, $rom: usage: inject name path type (offset)" -	[ "$2" = "/dev/null" ] && return 0 +	if [ "$2" = "/dev/null" ]; then +		return 0 +	fi -	eval "`setvars "" cbfsname _dest _t _offset`" -	cbfsname="$1"; _dest="${2##*../}"; _t="$3" +	cbfsname="$1" +	_dest="${2##*../}" +	blobtype="$3" -	if [ "$_t" = "fsp" ]; then -		[ $# -gt 3 ] && _offset="$4" -	else -		[ $# -gt 3 ] && _offset="-b $4" && [ -z "$4" ] && \ -		    $err "inject $*, $rom: offset given but empty (undefined)" +	_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 -	e "$_dest" f n && [ "$nukemode" != "nuke" ] && $err "!inject $dl_type" +	if [ "$nuke" != "nuke" ]; then +		x_ e "$_dest" f +	fi  	if [ "$cbfsname" = "IFD" ]; then -		[ "$nukemode" = "nuke" ] || "$ifdtool" $ifdprefix -i \ -		    $_t:$_dest "$rom" -O "$rom" || \ -		    $err "failed: inject '$_t' '$_dest' on '$rom'" -		[ "$nukemode" != "nuke" ] || "$ifdtool" $ifdprefix --nuke $_t \ -		    "$rom" -O "$rom" || $err "$rom: !nuke IFD/$_t" -		xchanged="y" -		return 0 -	elif [ "$nukemode" = "nuke" ]; then -		"$cbfstool" "$rom" remove -n "$cbfsname" || \ -		    $err "inject $rom: can't remove $cbfsname" -		xchanged="y" -		return 0 -	fi -	if [ "$_t" = "stage" ]; then # the only stage we handle is refcode -		x_ mkdir -p tmp; x_ rm -f "tmp/refcode" -		"$rmodtool" -i "$_dest" -o "tmp/refcode" || "!reloc refcode" -		"$cbfstool" "$rom" add-stage -f "tmp/refcode" -n "$cbfsname" \ -		    -t stage || $err "$rom: !add ref" +		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 -		"$cbfstool" "$rom" add -f "$_dest" -n "$cbfsname" \ -		    -t $_t $_offset || $err "$rom !add $_t ($_dest)" -	fi; xchanged="y"; : +		x_ "$cbfstool" "$rom" add -f "$_dest" -n "$cbfsname" \ +		    -t $blobtype $_offset +	fi + +	xchanged="y"  } -modify_mac_addresses() +# must be called from a subshell +check_vendor_hashes()  { -	[ "$nukemode" = "nuke" ] && \ -	    $err "Cannot modify MAC addresses while nuking vendor files" - -	# chkvars CONFIG_GBE_BIN_PATH -	[ -n "$CONFIG_GBE_BIN_PATH" ] || return 1 -	e "${CONFIG_GBE_BIN_PATH##*../}" f n && $err "missing gbe file" - -	x_ make -C util/nvmutil -	x_ mkdir -p tmp -	[ -L "tmp/gbe" ] && $err "tmp/gbe exists but is a symlink" -	[ -d "tmp/gbe" ] && $err "tmp/gbe exists but is a directory" -	if [ -e "tmp/gbe" ]; then -		[ -f "tmp/gbe" ] || $err "tmp/gbe exists and is not a file" -	fi -	x_ cp "${CONFIG_GBE_BIN_PATH##*../}" "tmp/gbe" - -	x_ "util/nvmutil/nvm" "tmp/gbe" setmac "$new_mac" - -	find "$tmpromdir" -maxdepth 1 -type f -name "*.rom" > "tmp/rom.list" \ -	    || $err "'$archive' -> Can't make tmp/rom.list - $dontflash" - -	while read -r _xrom; do -		[ -L "$_xrom" ] && continue -		[ -f "$_xrom" ] || continue -		"$ifdtool" $ifdprefix -i GbE:"tmp/gbe" "$_xrom" -O \ -		    "$_xrom" || $err "'$_xrom': Can't insert new GbE file" -		xchanged="y" -	done < "tmp/rom.list" -	printf "\nThe following GbE NVM words were written in '%s':\n" \ -	    "$archive" -	x_ util/nvmutil/nvm tmp/gbe dump +	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"  }  | 
