From 3ff4d68579595501b26815cb116aa6a9d7aa45b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Lewi=C5=84ski?= Date: Fri, 24 Jul 2026 08:32:29 +0000 Subject: [PATCH 1/3] src/sbom/Makefile.mk: Apply _ and tag to remaining deps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit e0813b32ac8e converted most git-backed SBOM components to the human-readable `_` software-version and a release tag as colloquial-version, but edk2-platforms and edk2-gop were missed and still emitted a bare commit hash with a tree hash as colloquial-version. openSIL likewise still recorded only a bare commit hash. Convert all three to follow suit: software-version now uses `_`, and where the template carries a colloquial-version field (edk2-platforms, edk2-gop) it now holds the latest release tag reachable from HEAD, selected the same way as the iPXE/vboot rules. openSIL has no colloquial-version field, so only its software-version changes. Decisions based on the RFC: https://datatracker.ietf.org/doc/rfc9393/ Upstream-Status: Pending Signed-off-by: Filip Lewiński --- src/sbom/Makefile.mk | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/sbom/Makefile.mk b/src/sbom/Makefile.mk index 02fecddc0c0..5e2251d0247 100644 --- a/src/sbom/Makefile.mk +++ b/src/sbom/Makefile.mk @@ -468,9 +468,10 @@ $(build-dir)/amd-agesa.json: $(src-dir)/amd-agesa.json $(CONFIG_AGESA_BINARY_PI_ sed -i "/software-version/d" $@; \ fi -# Record the git commit of the openSIL source tree as the SBOM version. +# Record the git commit of the openSIL source tree as the SBOM version, in the +# human-readable "_" form used for the other git-backed deps. # openSIL is an open-source library checked out as a submodule or external -# repo, so the commit hash is the canonical version identifier. +# repo, so the commit is the canonical version identifier. $(build-dir)/amd-opensil.json: $(src-dir)/amd-opensil.json | $(build-dir) cp $< $@ set -e; \ @@ -481,7 +482,7 @@ $(build-dir)/amd-opensil.json: $(src-dir)/amd-opensil.json | $(build-dir) done; \ fi; \ if [ -n "$$opensil_path" ] && [ -d "$$opensil_path" ]; then \ - comm_hash=$$(git -c safe.directory='*' -C "$$opensil_path" log -n 1 --format=%H 2>/dev/null); \ + comm_hash=$$(git -c safe.directory='*' -C "$$opensil_path" log -n 1 --format="%cs_%H" 2>/dev/null); \ if [ -n "$$comm_hash" ]; then \ sed -i -e "s//$$comm_hash/" $@; \ else \ @@ -574,9 +575,10 @@ $(build-dir)/payload-iPXE.json: $(src-dir)/payload-iPXE.json $(if $(ipxe-gitdir) fi # edk2-platforms is a separate git repository compiled into the edk2 payload. -# Record its commit hash (source-version) and tree hash (colloquial-version), -# mirroring the iPXE/payload git-backed component rules. The checkout lives at -# a deterministic path created during the edk2 payload build. +# Record its "_" (software-version) and latest release tag +# (colloquial-version), mirroring the iPXE/payload git-backed component rules. +# The checkout lives at a deterministic path created during the edk2 payload +# build. # # edk2-platforms has no standalone binary artifact (it is linked into the edk2 # payload FD), so for a component-integrity hash we record a sha256 over its @@ -593,9 +595,9 @@ $(build-dir)/payload-edk2-platforms.json: $(src-dir)/payload-edk2-platforms.json cp $< $@ set -e; \ if [ -e "$(edk2-platforms-git-dir)/.git" ]; then \ - git_tree_hash=$$(git --git-dir $(edk2-platforms-git-dir)/.git log -n 1 --format=%T); \ - git_comm_hash=$$(git --git-dir $(edk2-platforms-git-dir)/.git log -n 1 --format=%H); \ - sed -i -e "s//$$git_tree_hash/" -e "s//$$git_comm_hash/" $@; \ + git_comm_hash=$$(git --git-dir $(edk2-platforms-git-dir)/.git log -n 1 --format="%cs_%H"); \ + git_latest_rel=$$(git --git-dir $(edk2-platforms-git-dir)/.git tag --merged HEAD --sort=-creatordate | head -n1); \ + sed -i -e "s//$$git_latest_rel/" -e "s//$$git_comm_hash/" $@; \ src_hash=$$(git --git-dir $(edk2-platforms-git-dir)/.git archive HEAD | sha256sum | cut -d' ' -f1); \ $(build-dir)/goswid add-payload-file -o $@ -i $@ \ --name "edk2-platforms-source.tar" \ @@ -652,15 +654,16 @@ $(build-dir)/vga-bios-dgpu.json: $(src-dir)/vga-bios-dgpu.json $(wildcard $(CONF $(build-dir)/edk2-gop.json: $(src-dir)/edk2-gop.json $(wildcard $(CONFIG_EDK2_GOP_FILE)) | $(build-dir) $(build-dir)/goswid cp $< $@ # The GOP driver blob carries no embedded version; use the enclosing git - # repo's HEAD commit hash as a proxy (tree hash as colloquial-version), - # mirroring the Intel Flash Descriptor rule. + # repo's HEAD as a proxy: "_" (software-version) and the + # latest release tag (colloquial-version), mirroring the Intel Flash + # Descriptor rule. set -e; \ gop_git_root=$$(git -C "$$(dirname "$(CONFIG_EDK2_GOP_FILE)")" rev-parse --show-toplevel 2>/dev/null); \ if [ -n "$$gop_git_root" ]; then \ - gop_comm_hash=$$(git -C "$$gop_git_root" log -n 1 --format=%H); \ - gop_tree_hash=$$(git -C "$$gop_git_root" log -n 1 --format=%T); \ + gop_comm_hash=$$(git -C "$$gop_git_root" log -n 1 --format="%cs_%H"); \ + gop_latest_rel=$$(git -C "$$gop_git_root" tag --merged HEAD --sort=-creatordate | head -n1); \ sed -i -e "s//$$gop_comm_hash/" \ - -e "s//$$gop_tree_hash/" $@; \ + -e "s//$$gop_latest_rel/" $@; \ else \ sed -i -e "//d" -e "//d" $@; \ fi From 950787fd02b8ee0cb785a4c45f6c0ad5f0eb6e95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Lewi=C5=84ski?= Date: Tue, 4 Aug 2026 14:52:15 +0200 Subject: [PATCH 2/3] src/sbom/Makefile.mk: Deduplicate git version/tag derivation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every git-backed SBOM component derived its two version fields by hand-rolling the same two git commands, spelled three different ways (`--git-dir /.git`, `-C `, implicit cwd), with inconsistent stderr redirection and safe.directory handling. The latest-release tag alone was open-coded at five call sites, so changing how it is obtained meant a five-place edit. Introduce three `$(call)` helpers in the established strip_quotes idiom - sbom-git-comm-hash, sbom-git-latest-rel and sbom-git-toplevel-of - and route all call sites through them, so each git operation has exactly one definition. safe.directory is now relaxed uniformly rather than only for openSIL; containerized builds need it everywhere. With the command in one place, replace the open-coded `tag --merged HEAD --sort=-creatordate | head -n1` with the equivalent `git describe --tags --abbrev=0`, as suggested in review. Two flags are load-bearing: --tags is required because some component repositories (iPXE) carry only lightweight tags, which git describe ignores by default, and `|| true` is required because git describe exits 128 on repositories with no tags at all (3rdparty/vboot, 3rdparty/blobs), which would abort the recipes running under `set -e`. Output was verified identical for every checked-out component repository. coreboot.json deliberately keeps its own `^NN.NN$` tag filter: forks carry their own release tags, and git describe would return those (e.g. novacustom_nuc_box_v0.9.2) instead of the coreboot release. The comment there now says so, so a later cleanup does not "fix" it. No SBOM output changes. Upstream-Status: Pending Signed-off-by: Filip Lewiński --- src/sbom/Makefile.mk | 68 +++++++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/src/sbom/Makefile.mk b/src/sbom/Makefile.mk index 5e2251d0247..44013bbca04 100644 --- a/src/sbom/Makefile.mk +++ b/src/sbom/Makefile.mk @@ -53,6 +53,31 @@ CONFIG_SBOM_EDK2_LAN_ROM_PATH := $(call strip_quotes, $(CONFIG_SBOM_EDK2_LAN_ CONFIG_SBOM_IPXE_PATH := $(call strip_quotes, $(CONFIG_SBOM_IPXE_PATH)) CONFIG_SBOM_MANUFACTURER := $(call strip_quotes, $(CONFIG_SBOM_MANUFACTURER)) +# Shared git accessors for the git-backed components below. $(1) is the +# repository directory (a path inside it for sbom-git-toplevel-of). They expand +# to a command and are meant to be used in a shell command substitution: +# +# git_comm_hash=$$($(call sbom-git-comm-hash,3rdparty/vboot)); \ +# git_latest_rel=$$($(call sbom-git-latest-rel,3rdparty/vboot)); \ +# +# safe.directory is relaxed because checkouts are frequently owned by another +# user than the one running the build (containerized builds). +# +# software-version is the "_" of the repository HEAD. Errors +# are deliberately not silenced: a missing checkout would otherwise silently +# produce a component without a version. Callers that expect a miss append +# "2>/dev/null" themselves. +sbom-git-comm-hash = git -c safe.directory='*' -C "$(1)" log -n 1 --format="%cs_%H" +# colloquial-version is the most recent release tag reachable from HEAD. +# --tags is required, some of these repositories (iPXE) only carry lightweight +# tags, which git describe ignores by default. Repositories without any tag +# (3rdparty/vboot) make git describe fail, "|| true" keeps that from aborting +# recipes running under "set -e"; the placeholder is then substituted with an +# empty string and goswid omits the field. +sbom-git-latest-rel = git -c safe.directory='*' -C "$(1)" describe --tags --abbrev=0 2>/dev/null || true +# Repository enclosing a blob, for blobs whose repository is not known statically. +sbom-git-toplevel-of = git -C "$$(dirname "$(1)")" rev-parse --show-toplevel 2>/dev/null + # Select the correct payload directory for the used payload. Ideally we could just make this # a one-liner, but since the payload is generated externally (with an extra make command), we # have to hard code the paths here. @@ -220,10 +245,13 @@ $(build-dir)/compiler-%.json: $(src-dir)/compiler-%.json | $(build-dir)/goswid coreboot-gitdir := $(shell git rev-parse --git-dir) # coreboot version, format like "_" -# colloquial_version is latest coreboot release. Assumes static release tag format, might break. +# colloquial_version is the latest coreboot release, which is why this is the one +# component not using sbom-git-latest-rel: forks carry their own release tags +# (e.g. novacustom_nuc_box_v0.9.2), and git describe would return those instead +# of the coreboot release. Assumes static release tag format, might break. $(build-dir)/coreboot.json: $(src-dir)/coreboot.json $(coreboot-gitdir)/HEAD | $(build-dir)/goswid cp $< $@; \ - git_comm_hash=$$(git log -n 1 --format="%cs_%H"); \ + git_comm_hash=$$($(call sbom-git-comm-hash,.)); \ git_latest_rel=$$(git tag --merged HEAD | grep -E '^[0-9]{1,2}\.[0-9]{1,2}$$' | sort -V | tail -n1); \ sed -i -e "s//$$git_comm_hash/" \ -e "s//$$git_latest_rel/" \ @@ -313,7 +341,7 @@ $(build-dir)/intel-me.json: $(src-dir)/intel-me.json $(sbom-me-bin) | $(build-di $(build-dir)/intel-ifd.json: $(src-dir)/intel-ifd.json $(CONFIG_IFD_BIN_PATH) | $(build-dir)/goswid cp $< $@ set -e; \ - ifd_git_root=$$(git -C "$$(dirname "$(CONFIG_IFD_BIN_PATH)")" rev-parse --show-toplevel 2>/dev/null); \ + ifd_git_root=$$($(call sbom-git-toplevel-of,$(CONFIG_IFD_BIN_PATH))); \ ifd_readme="$$(dirname "$(CONFIG_IFD_BIN_PATH)")/README.md"; \ ifd_version=""; \ if [ -n "$$ifd_git_root" ]; then \ @@ -322,7 +350,7 @@ $(build-dir)/intel-ifd.json: $(src-dir)/intel-ifd.json $(CONFIG_IFD_BIN_PATH) | | grep -i 'Version:' \ | grep -Eo 'v([^,]+)'); \ fi; \ - ifd_comm_hash=$$(git -C "$$ifd_git_root" log -n 1 --format="%cs_%H"); \ + ifd_comm_hash=$$($(call sbom-git-comm-hash,$$ifd_git_root)); \ sed -i -e "s//$$ifd_comm_hash/" \ -e "s//$$ifd_version/" $@; \ else \ @@ -423,7 +451,7 @@ $(build-dir)/intel-fsp.json: $(src-dir)/intel-fsp.json $(CONFIG_FSP_FD_PATH) $(C fi; \ fsp_bios_version=""; sku_type=""; \ if [ "$(CONFIG_FSP_USE_REPO)" = "y" ]; then \ - fsp_git_root=$$(git -C "$$(dirname "$(CONFIG_FSP_FD_PATH)")" rev-parse --show-toplevel 2>/dev/null); \ + fsp_git_root=$$($(call sbom-git-toplevel-of,$(CONFIG_FSP_FD_PATH))); \ fsp_fd_abs=$$(realpath "$(CONFIG_FSP_FD_PATH)" 2>/dev/null || printf '%s\n' "$(CONFIG_FSP_FD_PATH)"); \ fsp_rel=$${fsp_fd_abs#$$fsp_git_root/}; \ sku_type=$${fsp_rel%/*}; \ @@ -482,7 +510,7 @@ $(build-dir)/amd-opensil.json: $(src-dir)/amd-opensil.json | $(build-dir) done; \ fi; \ if [ -n "$$opensil_path" ] && [ -d "$$opensil_path" ]; then \ - comm_hash=$$(git -c safe.directory='*' -C "$$opensil_path" log -n 1 --format="%cs_%H" 2>/dev/null); \ + comm_hash=$$($(call sbom-git-comm-hash,$$opensil_path) 2>/dev/null); \ if [ -n "$$comm_hash" ]; then \ sed -i -e "s//$$comm_hash/" $@; \ else \ @@ -546,8 +574,8 @@ vboot-gitdir := $(shell git -C 3rdparty/vboot rev-parse --absolute-git-dir 2>/de $(build-dir)/vboot.json: $(src-dir)/vboot.json $(if $(vboot-gitdir),$(vboot-gitdir)/HEAD,) | $(build-dir) $(build-dir)/goswid cp $< $@ - git_comm_hash=$$(git --git-dir 3rdparty/vboot/.git log -n 1 --format="%cs_%H"); \ - git_latest_rel=$$(git --git-dir 3rdparty/vboot/.git tag --merged HEAD --sort=-creatordate | head -n1); \ + git_comm_hash=$$($(call sbom-git-comm-hash,3rdparty/vboot)); \ + git_latest_rel=$$($(call sbom-git-latest-rel,3rdparty/vboot)); \ sed -i -e "s//$$git_latest_rel/" -e "s//$$git_comm_hash/" $@ # vboot is built from source as a per-stage static library rather than a # single blob; hash the ramstage vboot_fw.a as the representative artifact @@ -563,8 +591,8 @@ ipxe-gitdir := $(shell git -C payloads/external/iPXE/ipxe rev-parse --absolute-g # iPXE $(build-dir)/payload-iPXE.json: $(src-dir)/payload-iPXE.json $(if $(ipxe-gitdir),$(ipxe-gitdir)/HEAD,) | $(build-dir) $(build-dir)/goswid $(ipxe-swid-ready-dep) cp $< $@ - git_comm_hash=$$(git --git-dir payloads/external/iPXE/ipxe/.git log -n 1 --format="%cs_%H"); \ - git_latest_rel=$$(git --git-dir payloads/external/iPXE/ipxe/.git tag --merged HEAD --sort=-creatordate | head -n1); \ + git_comm_hash=$$($(call sbom-git-comm-hash,payloads/external/iPXE/ipxe)); \ + git_latest_rel=$$($(call sbom-git-latest-rel,payloads/external/iPXE/ipxe)); \ sed -i -e "s//$$git_latest_rel/" -e "s//$$git_comm_hash/" $@ # Hash the built iPXE ROM image (the artifact linked into CBFS) so the # component carries integrity info (CRA Annex I hash carry-through). @@ -595,10 +623,10 @@ $(build-dir)/payload-edk2-platforms.json: $(src-dir)/payload-edk2-platforms.json cp $< $@ set -e; \ if [ -e "$(edk2-platforms-git-dir)/.git" ]; then \ - git_comm_hash=$$(git --git-dir $(edk2-platforms-git-dir)/.git log -n 1 --format="%cs_%H"); \ - git_latest_rel=$$(git --git-dir $(edk2-platforms-git-dir)/.git tag --merged HEAD --sort=-creatordate | head -n1); \ + git_comm_hash=$$($(call sbom-git-comm-hash,$(edk2-platforms-git-dir))); \ + git_latest_rel=$$($(call sbom-git-latest-rel,$(edk2-platforms-git-dir))); \ sed -i -e "s//$$git_latest_rel/" -e "s//$$git_comm_hash/" $@; \ - src_hash=$$(git --git-dir $(edk2-platforms-git-dir)/.git archive HEAD | sha256sum | cut -d' ' -f1); \ + src_hash=$$(git -C $(edk2-platforms-git-dir) archive HEAD | sha256sum | cut -d' ' -f1); \ $(build-dir)/goswid add-payload-file -o $@ -i $@ \ --name "edk2-platforms-source.tar" \ --hash "$$src_hash"; \ @@ -658,12 +686,12 @@ $(build-dir)/edk2-gop.json: $(src-dir)/edk2-gop.json $(wildcard $(CONFIG_EDK2_GO # latest release tag (colloquial-version), mirroring the Intel Flash # Descriptor rule. set -e; \ - gop_git_root=$$(git -C "$$(dirname "$(CONFIG_EDK2_GOP_FILE)")" rev-parse --show-toplevel 2>/dev/null); \ + gop_git_root=$$($(call sbom-git-toplevel-of,$(CONFIG_EDK2_GOP_FILE))); \ if [ -n "$$gop_git_root" ]; then \ - gop_comm_hash=$$(git -C "$$gop_git_root" log -n 1 --format="%cs_%H"); \ - gop_latest_rel=$$(git -C "$$gop_git_root" tag --merged HEAD --sort=-creatordate | head -n1); \ - sed -i -e "s//$$gop_comm_hash/" \ - -e "s//$$gop_latest_rel/" $@; \ + gop_comm_hash=$$($(call sbom-git-comm-hash,$$gop_git_root)); \ + gop_latest_rel=$$($(call sbom-git-latest-rel,$$gop_git_root)); \ + sed -i -e "s//$$gop_latest_rel/" \ + -e "s//$$gop_comm_hash/" $@; \ else \ sed -i -e "//d" -e "//d" $@; \ fi @@ -686,8 +714,8 @@ $(build-dir)/edk2-lan-rom.json: $(src-dir)/edk2-lan-rom.json $(wildcard $(CONFIG # For standalone `make sbom`, use an existing checkout only. $(payload-swid): $(payload-swid-template) | $(build-dir) $(build-dir)/goswid $(payload-swid-ready-dep) cp $< $@;\ - git_comm_hash=$$(git --git-dir $(payload-git-dir-y)/.git log -n 1 --format="%cs_%H");\ - git_latest_rel=$$(git --git-dir $(payload-git-dir-y)/.git tag --merged HEAD --sort=-creatordate | head -n1); \ + git_comm_hash=$$($(call sbom-git-comm-hash,$(payload-git-dir-y)));\ + git_latest_rel=$$($(call sbom-git-latest-rel,$(payload-git-dir-y))); \ sed -i -e "s//$$git_latest_rel/" -e "s//$$git_comm_hash/" $@; if [ -s "$(CONFIG_PAYLOAD_FILE)" ]; then \ $(build-dir)/goswid add-payload-file -o $@ -i $@ \ From 52aa9a5db12bae485df310089497ebb4d068e9e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Lewi=C5=84ski?= Date: Wed, 5 Aug 2026 16:36:49 +0200 Subject: [PATCH 3/3] src/sbom: harden coreboot release tag detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Match point-release tags (24.02.01, 4.20.1) so a fork based on a release branch reports its real base, and abort instead of emitting an empty colloquial-version when the checkout carries no release tag at all, as happens on a shallow or blobless clone made without --tags. Upstream-Status: Pending Signed-off-by: Filip Lewiński --- src/sbom/Makefile.mk | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/sbom/Makefile.mk b/src/sbom/Makefile.mk index 44013bbca04..c03ac767d8f 100644 --- a/src/sbom/Makefile.mk +++ b/src/sbom/Makefile.mk @@ -248,11 +248,25 @@ coreboot-gitdir := $(shell git rev-parse --git-dir) # colloquial_version is the latest coreboot release, which is why this is the one # component not using sbom-git-latest-rel: forks carry their own release tags # (e.g. novacustom_nuc_box_v0.9.2), and git describe would return those instead -# of the coreboot release. Assumes static release tag format, might break. +# of the coreboot release. Releases are matched by tag name rather than by tag +# message ("coreboot version "), the less stable of the two: the name has +# kept its [.] shape since 4.0, while the message wording changed to +# "coreboot release " in 26.03. The optional third component covers point +# releases (24.02.01, 4.20.1); those only exist on release branches, so they are +# reachable only from a fork based on one. +# +# An empty result means the checkout carries no release tag at all, i.e. a +# shallow or blobless clone made without --tags. That is an error rather than an +# omitted field, unlike the tagless third-party repositories handled by +# sbom-git-latest-rel: for coreboot itself the release is always there to find. $(build-dir)/coreboot.json: $(src-dir)/coreboot.json $(coreboot-gitdir)/HEAD | $(build-dir)/goswid cp $< $@; \ git_comm_hash=$$($(call sbom-git-comm-hash,.)); \ - git_latest_rel=$$(git tag --merged HEAD | grep -E '^[0-9]{1,2}\.[0-9]{1,2}$$' | sort -V | tail -n1); \ + git_latest_rel=$$(git tag --merged HEAD | grep -E '^[0-9]{1,2}\.[0-9]{1,2}(\.[0-9]{1,2})?$$' | sort -V | tail -n1); \ + if [ -z "$$git_latest_rel" ]; then \ + echo "ERROR: no coreboot release tag reachable from HEAD, cannot set colloquial-version; run 'git fetch --tags'" >&2; \ + exit 1; \ + fi; \ sed -i -e "s//$$git_comm_hash/" \ -e "s//$$git_latest_rel/" \ $@;\