xref: /aosp_15_r20/external/coreboot/src/sbom/Makefile.mk (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1## SPDX-License-Identifier: GPL-2.0-only
2
3obj ?= build
4src ?= src
5build-dir = $(obj)/sbom
6src-dir = $(src)/sbom
7
8# Strip quotes from binary paths and SBOM file paths. Each binary path should have a
9# corresponding SBOM file path, but not every SBOM file path needs a binary path. That
10# is because binary files are only needed if they are used to extract information from
11# them which in turn can be included in the SBOM files (like version or config stuff).
12# But for some Software there are only SBOM files, which basically tell the most generic
13# information about that piece of Software. Ideally one would not need the binary files
14# at all, because extacting information out of mostly unknown binary blobs is a pain.
15CONFIG_ME_BIN_PATH         := $(call strip_quotes, $(CONFIG_ME_BIN_PATH))
16CONFIG_SBOM_ME_PATH        := $(call strip_quotes, $(CONFIG_SBOM_ME_PATH))
17CONFIG_FSP_S_FILE          := $(call strip_quotes, $(CONFIG_FSP_S_FILE))
18CONFIG_FSP_M_FILE          := $(call strip_quotes, $(CONFIG_FSP_M_FILE))
19CONFIG_FSP_T_FILE          := $(call strip_quotes, $(CONFIG_FSP_T_FILE))
20CONFIG_SBOM_FSP_PATH       := $(call strip_quotes, $(CONFIG_SBOM_FSP_PATH))
21CONFIG_PAYLOAD_FILE        := $(call strip_quotes, $(CONFIG_PAYLOAD_FILE))
22CONFIG_SBOM_PAYLOAD_PATH   := $(call strip_quotes, $(CONFIG_SBOM_PAYLOAD_PATH))
23CONFIG_EC_PATH             := $(call strip_quotes, $(CONFIG_EC_PATH))
24CONFIG_SBOM_EC_PATH        := $(call strip_quotes, $(CONFIG_SBOM_EC_PATH))
25CONFIG_SBOM_BIOS_ACM_PATH  := $(call strip_quotes, $(CONFIG_SBOM_BIOS_ACM_PATH))
26CONFIG_SBOM_SINIT_ACM_PATH := $(call strip_quotes, $(CONFIG_SBOM_SINIT_ACM_PATH))
27CONFIG_SBOM_COMPILER_PATH  := $(call strip_quotes, $(CONFIG_SBOM_COMPILER_PATH))
28
29# Select the correct payload directory for the used payload. Ideally we could just make this
30# a one-liner, but since the payload is generated externally (with an extra make command), we
31# have to hard code the paths here.
32ifeq ($(CONFIG_SBOM_PAYLOAD_GENERATE), y)
33payload-git-dir-$(CONFIG_PAYLOAD_BOOTBOOT)    = payloads/external/BOOTBOOT/bootboot
34payload-git-dir-$(CONFIG_PAYLOAD_DEPTHCHARGE) = payloads/external/depthcharge/depthcharge
35payload-git-dir-$(CONFIG_PAYLOAD_FILO)        = payloads/external/FILO/filo
36payload-git-dir-$(CONFIG_PAYLOAD_GRUB2)       = payloads/external/GRUB2/grub2
37payload-git-dir-$(CONFIG_PAYLOAD_LINUXBOOT)   = payloads/external/LinuxBoot/linuxboot
38payload-git-dir-$(CONFIG_PAYLOAD_SEABIOS)     = payloads/external/SeaBIOS/seabios
39payload-git-dir-$(CONFIG_PAYLOAD_SKIBOOT)     = payloads/external/skiboot/skiboot
40#payload-git-dir-$(CONFIG_PAYLOAD_TIANOCORE)   = payloads/external/tianocore/
41payload-git-dir-$(CONFIG_PAYLOAD_UBOOT)       = payloads/external/U-Boot/u-boot
42payload-git-dir-$(CONFIG_PAYLOAD_IPXE)        = payloads/external/iPXE/ipxe
43ifneq ($(payload-git-dir-y),)
44# only proceed with payload sbom data, if one of the above payloads were selected (should be guarded by Kconfig as well)
45# e.g. payload-git-dir-y=payloads/external/SeaBIOS/seabios -> payload-json-file=$(build-dir)/payload-SeaBIOS.json
46payload-swid = $(build-dir)/payload-$(subst /,,$(dir $(patsubst payloads/external/%,%,$(payload-git-dir-y)))).json
47payload-swid-template = $(patsubst $(build-dir)/%.json,$(src-dir)/%.json,$(payload-swid))
48endif
49endif
50
51# Add all SBOM files into the swid-files-y target. This target contains all
52# .json, .ini, .uswid, .xml, .pc SBOM files that are later merged into one uSWID SBOM file.
53# Some of these have an option that this Makefile generates/extracts some information from
54# binary files in order to give more complete/detailed information inside the SBOM file.
55# These files are either in src/sbom/ or build/sbom (if they are generated).
56swid-files-$(CONFIG_SBOM_ME) += $(if $(CONFIG_SBOM_ME_GENERATE), $(build-dir)/intel-me.json, $(CONFIG_SBOM_ME_PATH))
57swid-files-$(CONFIG_SBOM_PAYLOAD) += $(if $(CONFIG_SBOM_PAYLOAD_GENERATE), $(payload-swid), $(CONFIG_SBOM_PAYLOAD_PATH))
58# TODO think about just using one CoSWID tag for all intel-microcode instead of one for each. maybe put each microcode into files entity of CoSWID tag?
59swid-files-$(CONFIG_SBOM_MICROCODE) += $(patsubst 3rdparty/intel-microcode/intel-ucode/%, $(build-dir)/intel-microcode-%.json, $(filter 3rdparty/intel-microcode/intel-ucode/%, $(cpu_microcode_bins)))
60swid-files-$(CONFIG_SBOM_MICROCODE) += $(patsubst ${FIRMWARE_LOCATION}/UcodePatch_%.bin, $(build-dir)/amd-microcode-%.json, $(filter ${FIRMWARE_LOCATION}/UcodePatch_%.bin, $(cpu_microcode_bins)))
61swid-files-$(CONFIG_SBOM_FSP) += $(CONFIG_SBOM_FSP_PATH)
62swid-files-$(CONFIG_SBOM_EC) += $(CONFIG_SBOM_EC_PATH)
63swid-files-$(CONFIG_SBOM_BIOS_ACM) += $(CONFIG_BIOS_ACM_PATH)
64swid-files-$(CONFIG_SBOM_SINIT_ACM) += $(CONFIG_SINIT_ACM_PATH)
65
66vboot-pkgconfig-files = $(obj)/external/vboot_reference-bootblock/vboot_host.pc $(obj)/external/vboot_reference-romstage/vboot_host.pc $(obj)/external/vboot_reference-ramstage/vboot_host.pc $(obj)/external/vboot_reference-postcar/vboot_host.pc
67swid-files-$(CONFIG_SBOM_VBOOT) += $(vboot-pkgconfig-files)
68$(vboot-pkgconfig-files): $(VBOOT_LIB_bootblock) $(VBOOT_LIB_romstage) $(VBOOT_LIB_ramstage) $(VBOOT_LIB_postcar) # src/security/vboot/Makefile.mk
69
70ifeq ($(CONFIG_SBOM_COMPILER),y)
71compiler-toolchain = $(CC_bootblock) $(CC_romstage) $(CC_ramstage) $(CC_postcar) $(CC_verstage) $(LD_bootblock) $(LD_romstage) $(LD_ramstage) $(LD_postcar) $(LD_verstage) $(AS_bootblock) $(AS_romstage) $(AS_ramstage) $(AS_postcar) $(AS_verstage)
72swid-files-compiler = $(CONFIG_SBOM_COMPILER_PATH)
73endif
74
75# include all licenses used in coreboot. Ideally we would only include the licenses,
76# which are used in this build
77coreboot-licenses = $(foreach license, $(patsubst %.txt, %, $(filter-out retained-copyrights.txt, $(patsubst LICENSES/%, %, $(wildcard LICENSES/*)))), https://spdx.org/licenses/$(license).html)
78
79# only include CBFS SBOM section if there is any data for it
80ifeq ($(CONFIG_SBOM),y)
81cbfs-files-y += sbom
82sbom-file = $(build-dir)/sbom.uswid
83sbom-type = raw
84endif
85
86## Build final SBOM (Software Bill of Materials) file in uswid format
87
88$(build-dir)/sbom.uswid: $(build-dir)/coreboot.json $$(swid-files-y) $(swid-files-compiler) | $(build-dir)/goswid $(build-dir)
89	echo "    SBOM      " $^
90	$(build-dir)/goswid convert -o $@ \
91		--parent $(build-dir)/coreboot.json \
92		$(if $(swid-files-y), --requires $$(echo $(swid-files-y) | tr ' ' ','),) \
93		$(if $(swid-files-compiler), --compiler $(swid-files-compiler),)
94
95# all build files depend on the $(build-dir) directory being created
96$(build-dir):
97	mkdir -p $(build-dir)
98
99$(build-dir)/goswid: | $(build-dir)
100	echo "    SBOM      building goswid tool"
101	cd util/goswid; \
102	GOPATH=$(abspath build/go) GO111MODULE=on go build -modcacherw -o $(abspath $@) ./cmd/goswid
103
104## Generate all .json files
105
106$(build-dir)/compiler-%.json: $(src-dir)/compiler-%.json | $(build-dir)/goswid
107	cp $< $@
108	for tool in $$(echo $(compiler-toolchain) | tr ' ' '\n' | sort | uniq); do \
109		version=$$($$tool --version 2>&1 | head -n 1 | grep -Eo '([0-9]+\.[0-9]+\.*[0-9]*)'); \
110		$(build-dir)/goswid add-payload-file -o $@ -i $@ --name $$(basename $$tool) --version $$version; \
111	done
112
113$(build-dir)/coreboot.json: $(src-dir)/coreboot.json .git/HEAD | $(build-dir)/goswid
114	cp $< $@
115	git_tree_hash=$$(git log -n 1 --format=%T);\
116	git_comm_hash=$$(git log -n 1 --format=%H);\
117	sed -i -e "s/<colloquial_version>/$$git_tree_hash/" -e "s/<software_version>/$$git_comm_hash/" $@;\
118	$(build-dir)/goswid add-license -o $@ -i $@ $(coreboot-licenses)
119
120$(build-dir)/intel-me.json: $(src-dir)/intel-me.json $(CONFIG_ME_BIN_PATH) | $(build-dir)
121	cp $< $@
122	#TODO put more Intel Management Engine metadata in sbom file
123
124
125$(build-dir)/generic-fsp.json: $(src-dir)/generic-fsp.json $(CONFIG_FSP_S_FILE) $(CONFIG_FSP_T_FILE) $(CONFIG_FSP_M_FILE) | $(build-dir)/goswid
126	cp $(src-dir)/generic-fsp.json $@
127ifneq ($(CONFIG_FSP_S_FILE),)
128	echo "    SBOM      Adding FSP-S"
129	$(build-dir)/goswid add-payload-file -o $@ -i $@ --name "FSP-S"
130endif
131ifneq ($(CONFIG_FSP_T_FILE),)
132	echo "    SBOM      Adding FSP-T"
133	$(build-dir)/goswid add-payload-file -o $@ -i $@ --name "FSP-T"
134endif
135ifneq ($(CONFIG_FSP_M_FILE),)
136	echo "    SBOM      Adding FSP-M"
137	$(build-dir)/goswid add-payload-file -o $@ -i $@ --name "FSP-M"
138endif
139
140$(build-dir)/intel-microcode-%.json: $(src-dir)/intel-microcode.json 3rdparty/intel-microcode/intel-ucode/% | $(build-dir) $(build-dir)/goswid
141	cp $< $@
142	year=$$(hexdump --skip 8 --length 2 --format '"%04x"' $(word 2,$^));\
143	day=$$(hexdump --skip 10 --length 1 --format '"%02x"' $(word 2,$^));\
144	month=$$(hexdump --skip 11 --length 1 --format '"%02x"' $(word 2,$^));\
145	sed -i "s/<software_version>/$$year-$$month-$$day/" $@
146	#TODO add cpuid (processor family, model, stepping) as extra attribute
147
148$(build-dir)/amd-microcode-%.json: $(src-dir)/amd-microcode.json ${FIRMWARE_LOCATION}/UcodePatch_%.bin | $(build-dir) $(build-dir)/goswid
149	cp $< $@
150	year=$$(hexdump --skip 0 --length 2 --format '"%04x"' $(word 2,$^));\
151	day=$$(hexdump --skip 2 --length 1 --format '"%02x"' $(word 2,$^));\
152	month=$$(hexdump --skip 3 --length 1 --format '"%02x"' $(word 2,$^));\
153	sed -i "s/<software_version>/$$year-$$month-$$day/" $@
154
155$(payload-swid): $(payload-swid-template) $(CONFIG_PAYLOAD_FILE) | $(build-dir)
156	cp $< $@;\
157	git_tree_hash=$$(git --git-dir $(payload-git-dir-y)/.git log -n 1 --format=%T);\
158	git_comm_hash=$$(git --git-dir $(payload-git-dir-y)/.git log -n 1 --format=%H);\
159	sed -i -e "s/<colloquial_version>/$$git_tree_hash/" -e "s/<software_version>/$$git_comm_hash/" $@;
160