-
Notifications
You must be signed in to change notification settings - Fork 6
/
Makefile.inc
321 lines (269 loc) · 12.3 KB
/
Makefile.inc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
# vim: syntax=make
#
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
# This file should be paramterized and included by platform Makefile.
# See `examples/qemu-x86_64/Makefile` for one.
MAKEFLAGS += --warn-undefined-variables
.PHONY: always-build build clean clean-coreboot clean-initramfs clean-kernel coreboot-toolchain initramfs kernel wipe wipe-initramfs wipe-coreboot wipe-kernel
.DEFAULT_GOAL: build
.SUFFIXES:
ifndef PLATFORM
$(error Please define PLATFORM)
endif
ifndef OSF_BUILDER_DIR
$(error Please define OSF_BUILDER_DIR)
endif
ifndef CONFIGS_DIR
$(error Please define CONFIGS_DIR)
endif
ifndef PATCHES_DIR
$(error Please define PATCHES_DIR)
endif
# If defined, specifies URL overrides to be applied when fetching deps.
URL_OVERRIDES ?=
# Version of the firmware being built.
VERSION ?= 0.0.0
HASH_MODE ?= strict
BUILD_DIR ?= $(realpath $(CURDIR))/build
PLATFORM_BUILD_DIR ?= $(BUILD_DIR)/$(PLATFORM)
ROM_OUT ?= $(PLATFORM_BUILD_DIR)/osf-$(PLATFORM).rom
# Absolutize CONFIGS_DIR
CONFIGS_DIR := $(realpath $(CONFIGS_DIR))
CONFIG ?= $(CONFIGS_DIR)/config-$(PLATFORM).json
KERNEL_CONFIG ?= $(CONFIGS_DIR)/kernel.config
COREBOOT_CONFIG ?= $(CONFIGS_DIR)/coreboot.config-$(PLATFORM)
TOOLS_DIR := $(realpath $(OSF_BUILDER_DIR)/tools)
URL_OVERRIDES_ABS = $(realpath $(URL_OVERRIDES))
# We build initramfs every time to pick up possible changes.
# If you are not actively working on u-root, feel free to set this to 0.
ALWAYS_BUILD_INITRAMFS ?= 1
# Same for the kernel and coreboot.
ALWAYS_BUILD_KERNEL ?= 1
ALWAYS_BUILD_COREBOOT ?= 1
_WIPE_CONFIRMED ?= 0
ALL_CONFIGS := $(wildcard $(CONFIGS_DIR)/*.json)
DEFAULT_GETDEPS_TOOL ?= $(PLATFORM_BUILD_DIR)/getdeps
GETDEPS_TOOL ?= $(DEFAULT_GETDEPS_TOOL)
VPD_TOOL ?= $(TOOLS_DIR)/vpd
FLASHROM_TOOL ?= $(TOOLS_DIR)/flashrom
CBNT_PROV_TOOL ?= $(TOOLS_DIR)/cbnt-prov
FINAL_CONFIG_OUT := $(PLATFORM_BUILD_DIR)/final_config.json
NPROC ?= $(shell nproc --all --ignore=1)
INITRAMFS_BUILD_DIR := $(PLATFORM_BUILD_DIR)/initramfs
INITRAMFS_DEPS_FLAG := $(PLATFORM_BUILD_DIR)/.initramfs-deps
INITRAMFS_PATCH_FLAG := $(PLATFORM_BUILD_DIR)/.initramfs-patch
ifndef INITRAMFS_OUT
INITRAMFS_OUT := $(INITRAMFS_BUILD_DIR)/initramfs_linuxboot.amd64.cpio
endif
# By default, build initramfs but a prebuilt one can be provided via INITRAMFS_IN.
INITRAMFS_IN ?= $(INITRAMFS_OUT)
KERNEL_BUILD_DIR := $(PLATFORM_BUILD_DIR)/kernel
KERNEL_CONFIG_OUT := $(KERNEL_BUILD_DIR)/.config
KERNEL_DEPS_FLAG := $(PLATFORM_BUILD_DIR)/.kernel-deps
KERNEL_PATCH_FLAG := $(PLATFORM_BUILD_DIR)/.kernel-patch
KERNEL_OUT_DEFAULT := $(KERNEL_BUILD_DIR)/arch/x86/boot/bzImage
ifndef KERNEL_OUT
KERNEL_OUT := $(KERNEL_OUT_DEFAULT)
endif
# Prebuilt kernel can be provided via KERNEL_IN.
KERNEL_IN ?= $(KERNEL_OUT)
COREBOOT_BUILD_DIR := $(PLATFORM_BUILD_DIR)/coreboot
COREBOOT_CONFIG_OUT := $(COREBOOT_BUILD_DIR)/.config
COREBOOT_TOOLCHAIN_OUT := $(COREBOOT_BUILD_DIR)/util/crossgcc/xgcc
COREBOOT_OUT := $(COREBOOT_BUILD_DIR)/build/coreboot.rom
COREBOOT_DEPS_FLAG := $(PLATFORM_BUILD_DIR)/.coreboot-deps
COREBOOT_PATCH_FLAG := $(PLATFORM_BUILD_DIR)/.coreboot-patch
COREBOOT_TOOLCHAIN_FLAG := $(PLATFORM_BUILD_DIR)/.coreboot-toolchain
COREBOOT_TOOLCHAIN_CACHE_ENABLE ?= 1
# coreboot Intel blobs
ifdef COREBOOT_BLOBS_DIR
COREBOOT_BLOBS_DIR := $(realpath $(COREBOOT_BLOBS_DIR))
endif
UROOT_BOOT_CMDS := fbnetboot localboot systemboot
UROOT_EXP_CMDS := cbmem dmidecode modprobe ipmidump
UROOT_BASE_CMDS ?= \
core \
$(addprefix github.com/u-root/u-root/cmds/boot/, $(UROOT_BOOT_CMDS)) \
$(addprefix github.com/u-root/u-root/cmds/exp/, $(UROOT_EXP_CMDS)) \
UROOT_ADDITIONAL_CMDS ?=
UROOT_ADDITIONAL_GOPATH ?=
BASE_FILES ?= $(FLASHROM_TOOL):bin/flashrom $(VPD_TOOL):bin/vpd
UROOT_ADDITIONAL_FILES ?=
UINIT_CMD ?= systemboot
# Shorthand for building the firmware.
build: $(ROM_OUT)
# Main output product - firmware with VPD variables.
$(ROM_OUT): $(COREBOOT_OUT)
$(VPD_TOOL) -f "$<" -O -i RO_VPD -s internal_versions="`cat $(FINAL_CONFIG_OUT)`"
[ -z "$(VERSION)" ] || $(VPD_TOOL) -f "$<" -i RO_VPD -s firmware_version=$(VERSION)
$(VPD_TOOL) -f "$<" -O -i RW_VPD || true # Format RW_VPD region, if present.
[ -f "$(CURDIR)/vpd.sh" ] && bash "$(CURDIR)/vpd.sh" || echo "$(CURDIR)/vpd.sh doesn't exist"
cp "$<" "$@"
@echo '***' >&2
@echo '*** Build done, $@' >&2
@echo '***' >&2
# ========================
# === coreboot section ===
# ========================
# coreboot build - produces a firmware image, depends on payload (kernel + initramfs), config and toolchain.
$(COREBOOT_OUT): $(KERNEL_IN) $(COREBOOT_CONFIG_OUT) $(COREBOOT_PATCH_FLAG) $(COREBOOT_TOOLCHAIN_FLAG)
@# Parallel builds are not always reliable, hence -j1.
UPDATED_SUBMODULES=1 MAKEFLAGS= $(MAKE) -C $(COREBOOT_BUILD_DIR) -j1
ifeq "$(ALWAYS_BUILD_COREBOOT)" "1"
$(COREBOOT_OUT): always-build
endif
# Applies coreboot patches for this platform, if any.
$(COREBOOT_PATCH_FLAG): $(realpath $(wildcard $(PATCHES_DIR)/coreboot-$(PLATFORM)-*))
$(call patch,$(COREBOOT_BUILD_DIR),$^)
touch $@
# Toolchain version identifier - same as in coreboot/util/crossgcc/buildgcc.
# Produces something like "2021-04-06_7014f825", uniquely identifes the toolchain and is used to cache it.
CROSSGCC_VERSION = $(shell git -C $(COREBOOT_BUILD_DIR)/util/crossgcc log -n 1 --pretty=%cd --date=short .)_$(shell git -C $(COREBOOT_BUILD_DIR)/util/crossgcc log -n 1 --pretty=%h .)
COREBOOT_TOOLCHAIN_CACHE = $(BUILD_DIR)/coreboot-toolchain-$(CROSSGCC_VERSION).tar
# Flag signaling that coreboot toolchain build is done.
# Depends on IASL binary which is built last during the toolchain build, meaning it's complete (in case build was interrupted).
# Toolchain cache archive is created here, unless already exists.
$(COREBOOT_TOOLCHAIN_FLAG): $(COREBOOT_TOOLCHAIN_OUT)/bin/iasl
ifeq "$(COREBOOT_TOOLCHAIN_CACHE_ENABLE)" "1"
if ! [ -f "$(COREBOOT_TOOLCHAIN_CACHE)" ]; then \
tar cf $(COREBOOT_TOOLCHAIN_CACHE).tmp -C $(dir $(COREBOOT_TOOLCHAIN_OUT)) $(notdir $(COREBOOT_TOOLCHAIN_OUT)) && \
mv $(COREBOOT_TOOLCHAIN_CACHE).tmp $(COREBOOT_TOOLCHAIN_CACHE); \
fi
endif
touch $@
# Provides the crossgcc toolchain. Uses cache if enabled and available, otherwise build from sources.
$(COREBOOT_TOOLCHAIN_OUT)/bin/iasl: $(COREBOOT_DEPS_FLAG) $(COREBOOT_PATCH_FLAG)
if [ -f $(COREBOOT_TOOLCHAIN_CACHE) ]; then \
echo Using cached toolchain from $(COREBOOT_TOOLCHAIN_CACHE) >&2; \
tar xf $(COREBOOT_TOOLCHAIN_CACHE) -C $(dir $(COREBOOT_TOOLCHAIN_OUT)); \
touch $@; \
else \
COREBOOT_BUILD_DIR=$(COREBOOT_BUILD_DIR) CPUS=$(NPROC) MAKE=$(MAKE) TOOLS_DIR=$(TOOLS_DIR) \
$(TOOLS_DIR)/build_toolchain.sh; \
fi
# Creates coreboot config file using the user-provided one and feeding it to make olddefconfig.
$(COREBOOT_CONFIG_OUT): $(COREBOOT_CONFIG) $(COREBOOT_DEPS_FLAG) $(COREBOOT_TOOLCHAIN_FLAG)
cp $(COREBOOT_CONFIG) $(COREBOOT_CONFIG_OUT)
ifndef NO_INTEL_BLOBS
if [ -d "$(COREBOOT_BLOBS_DIR)" ]; then \
echo Using provided coreboot Intel blobs FSP, ME and microcode from $(COREBOOT_BLOBS_DIR) >&2; \
sed -i "s|CONFIG_CPU_UCODE_BINARIES=.*|CONFIG_CPU_UCODE_BINARIES=\"$(COREBOOT_BLOBS_DIR)/microcode.mcb\"|" $@; \
sed -i "s|CONFIG_FSP_T_FILE=.*|CONFIG_FSP_T_FILE=\"$(COREBOOT_BLOBS_DIR)/Server_T.fd\"|" $@; \
sed -i "s|CONFIG_FSP_M_FILE=.*|CONFIG_FSP_M_FILE=\"$(COREBOOT_BLOBS_DIR)/Server_M.fd\"|" $@; \
sed -i "s|CONFIG_FSP_S_FILE=.*|CONFIG_FSP_S_FILE=\"$(COREBOOT_BLOBS_DIR)/Server_S.fd\"|" $@; \
sed -i "s|CONFIG_IFD_BIN_PATH=.*|CONFIG_IFD_BIN_PATH=\"$(COREBOOT_BLOBS_DIR)/flashregion_0_flashdescriptor.bin\"|" $@; \
sed -i "s|CONFIG_ME_BIN_PATH=.*|CONFIG_ME_BIN_PATH=\"$(COREBOOT_BLOBS_DIR)/flashregion_2_intel_me.bin\"|" $@; \
fi
! grep -q CONFIG_INTEL_CBNT_PROV_EXTERNAL_BIN=y $@ || \
sed -i "s|CONFIG_INTEL_CBNT_PROV_EXTERNAL_BIN_PATH=.*|CONFIG_INTEL_CBNT_PROV_EXTERNAL_BIN_PATH=\"$(CBNT_PROV_TOOL)\"|" $@
endif
sed -i "s|CONFIG_PAYLOAD_FILE=.*|CONFIG_PAYLOAD_FILE=\"$(KERNEL_IN)\"|" $@
MAKEFLAGS= $(MAKE) -C $(COREBOOT_BUILD_DIR) olddefconfig
clean-coreboot:
rm -f $(COREBOOT_OUT)
[ -d $(COREBOOT_BUILD_DIR) ] && MAKEFLAGS= $(MAKE) -C $(COREBOOT_BUILD_DIR) clean
wipe-coreboot:
rm -rf $(COREBOOT_BUILD_DIR) $(COREBOOT_DEPS_FLAG) $(COREBOOT_PATCH_FLAG) $(COREBOOT_TOOLCHAIN_FLAG)
# ======================
# === Kernel section ===
# ======================
# Top-level initramfs target, for use by humans.
kernel: $(KERNEL_OUT)
# Kernel build target. Requires initrmafs image, config and patches.
ifneq "$(INITRAMFS_IN)" ""
$(KERNEL_OUT): $(INITRAMFS_IN) $(KERNEL_CONFIG_OUT) $(KERNEL_PATCH_FLAG)
else
$(KERNEL_OUT): $(KERNEL_CONFIG_OUT) $(KERNEL_PATCH_FLAG)
endif
@# If lzma(1) is not available, kernel build will fall back to gzip and we don't want that.
@if ! lzma -h > /dev/null 2>/dev/null; then \
echo ' *** Please install the lzma CLI utility.' >&2; \
echo ' *** In RedHat distros it`s provided by xz-lzma-compat, in Debian/Ubuntu it`s provided by xz-utils.' >&2; \
exit 1; \
fi
MAKEFLAGS= $(MAKE) -C $(KERNEL_BUILD_DIR) -j$(NPROC) KCFLAGS=-pipe
[ "$@" = "$(KERNEL_OUT_DEFAULT)" ] || cp -v "$(KERNEL_OUT_DEFAULT)" "$@"
ifeq "$(ALWAYS_BUILD_KERNEL)" "1"
$(KERNEL_OUT): always-build
endif
$(KERNEL_CONFIG_OUT): $(KERNEL_CONFIG) $(KERNEL_DEPS_FLAG)
cp $(KERNEL_CONFIG) $@
sed -i "s|CONFIG_INITRAMFS_SOURCE=.*|CONFIG_INITRAMFS_SOURCE=\"$(INITRAMFS_IN)\"|" $@
MAKEFLAGS= $(MAKE) -C $(KERNEL_BUILD_DIR) olddefconfig
$(KERNEL_PATCH_FLAG): $(realpath $(wildcard $(PATCHES_DIR)/kernel-*))
$(call patch,$(KERNEL_BUILD_DIR),$^)
touch $@
clean-kernel:
rm -f $(KERNEL_OUT)
[ -d $(KERNEL_BUILD_DIR) ] && MAKEFLAGS= $(MAKE) -C $(KERNEL_BUILD_DIR) clean
wipe-kernel:
rm -rf $(KERNEL_BUILD_DIR) $(KERNEL_DEPS_FLAG) $(KERNEL_PATCH_FLAG)
# =========================
# === Initramfs section ===
# =========================
# Top-level initramfs target, for use by humans.
initramfs: $(INITRAMFS_OUT)
# Initramfs build target.
$(INITRAMFS_OUT): $(INITRAMFS_DEPS_FLAG) $(INITRAMFS_PATCH_FLAG)
GO111MODULE=off \
GOROOT=$(INITRAMFS_BUILD_DIR)/go \
GOCACHE=$(INITRAMFS_BUILD_DIR)/go/.cache \
GOPATH=$(INITRAMFS_BUILD_DIR)/gopath:$(UROOT_ADDITIONAL_GOPATH) \
$(INITRAMFS_BUILD_DIR)/go/bin/go run github.com/u-root/u-root \
-build=bb -uroot-source $(INITRAMFS_BUILD_DIR)/gopath/src/github.com/u-root/u-root -o $@ -uinitcmd=$(UINIT_CMD) \
$(addprefix -files=,$(BASE_FILES) $(UROOT_ADDITIONAL_FILES)) \
$(UROOT_ADDITIONAL_CMDS) \
$(UROOT_BASE_CMDS) \
|| { rm -f $@; exit 1; }
ifeq "$(ALWAYS_BUILD_INITRAMFS)" "1"
$(INITRAMFS_OUT): always-build
endif
$(INITRAMFS_PATCH_FLAG): $(realpath $(wildcard $(PATCHES_DIR)/initramfs-*))
$(call patch,$(INITRAMFS_BUILD_DIR),$^)
touch $@
clean-initramfs:
rm -f $(INITRAMFS_OUT)
wipe-initramfs:
rm -rf $(INITRAMFS_BUILD_DIR) $(INITRAMFS_DEPS_FLAG) $(INITRAMFS_PATCH_FLAG)
# ====================
# === Misc section ===
# ====================
# If any of the configs is not there, give the user a clear message (probably PLATFORM is incorrect).
$(CONFIG) $(COREBOOT_CONFIG) $(KERNEL_CONFIG):
@echo '***' >&2
@echo '*** Missing config - $@' >&2
@echo '***' >&2
@false
# Rebuild the getdeps tool if necessary.
$(DEFAULT_GETDEPS_TOOL): $(wildcard $(OSF_BUILDER_DIR)/getdeps/*.go)
mkdir -p $(PLATFORM_BUILD_DIR)
GO111MODULE=off GOBIN=$(dir $@) go get $(OSF_BUILDER_DIR)/getdeps
# Run the getdeps tool for a component (initramfs, kernel, coreboot) and create a flag file.
# The flag file is used to avoid re-running unless JSON configs have changed.
$(PLATFORM_BUILD_DIR)/.%-deps: $(CONFIG) $(GETDEPS_TOOL) $(ALL_CONFIGS)
@if [ -f "$@" -a $(_WIPE_CONFIRMED) -eq 0 ]; then \
echo "WARNING: A full wipe is being triggered, it will remove build artifacts and git repos under $(PLATFORM_BUILD_DIR), are you sure to continue? (y/n)"; \
read ans; \
if [ "$$ans" = "y" ]; then \
echo continue; \
else \
echo exit 1; exit 1; \
fi \
fi
$(eval _WIPE_CONFIRMED=1)
mkdir -p $(PLATFORM_BUILD_DIR)
cd $(PLATFORM_BUILD_DIR) && $(GETDEPS_TOOL) --components $* -c $(CONFIG) -H $(HASH_MODE) --url-overrides=$(URL_OVERRIDES_ABS) -o $(FINAL_CONFIG_OUT)
touch $@
define patch # dir,patches
[ -z "$2" ] || { cd $1 && for p in $2; do patch -d gopath/src/github.com/u-root/u-root -p 1 -N -b --verbose -i $$p; done }
endef
clean: clean-initramfs clean-kernel clean-coreboot
rm -f $(OUT)
wipe:
rm -rf $(PLATFORM_BUILD_DIR)
# Dummy target to depend on when forcing rebuild.
always-build:
@true